01.Java父子类继承详解

一、继承的概念

  • 继承是Java语言的三大特性之一,通过子类继承父类的方式,让代码方便扩展和管理。
  • Java中,类与类之间可以存在继承关系,处于继承关系的两个类,通常简称为父类和子类。
  • 子类使用extends关键字继承父类,extends单词是扩展的意思,表意为子类是对父类的扩展。
  • Java中的类只能单一继承,例如C继承B,B继承A,可以多层级继承,但每个类只能继承一个父类
  • Java中所有类都隐式继承了Object类,Object类是所有类的根系父类

父子类继承语法示例

  • 创建一个父类Parent
  • 创建一个子类Child,使用extends关键字继承Parent类
public class Parent { /* 父类属性和方法 */ } 
public class Child extends Parent { /* 新增属性和方法 */ }

二、继承的特点(代码实例)

2.1、子类继承父类所有非私有(private)属性和方法
  • 子类无需显式定义父类中存在的方法和字段,可直接调用
  • 父子类继承中,会优先在子类中或局域函数方法内寻找对应变量,最后在父类中寻找(如果存在多层级继承,则根据层级往上寻找),如果都没有则直接报错。
/** 创建一个父类*/
public class Parent {
    public int money = 1_0000_0000;
    public void say(){
        System.out.println("说话");
    }
 }
 
 /** 子类*/
public class Child extends Parent { }


/** 测试类*/
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        System.out.println(child.money); //输出结果:1_0000_0000 
        System.out.println(child.say()); //输出结果:说话
    }
}
2.2、使用super关键字调用父类非私有(private)构造函数,属性,方法
/** 创建一个父类*/
public class Parent {
    public String name = "father";
 }
 
 /** 子类*/
public class Child extends Parent {
    public String name = "son";
    public void say(){
        String name = "函数内字段"
        System.out.println(super.name);
        System.out.println(this.name);
        System.out.println(name);
    }
}


/** 测试类*/
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        System.out.println(child.say());
        // 最终输出
        // father
        // son
        // 函数内字段
     }
}
superthis的区别
  • this指向当前类引用标识(当前类名空间)
    • 用于访问本类的方法和字段
    • this()访问本类构造函数
    • this.属性字段(访问本类)
    • this.函数方法(访问本类)
  • super指向直接继承的父类引用(父类空间)
    • super()访问父类的构造函数
    • super.属性字段(访问父类)
    • super.函数方法(访问父类)

2.3、方法重写
  • 子类重新解释父类的函数行为(在实际业务场景中,方法重写很常见/划重点
  • 子类重写父类的方法通过@Override修饰方法头实现【规范】
  • 父类中private修饰的方法,构造函数,static,不可重写
  • 重写的方法其访问修饰符权限不能更低一级

代码实例

// 创建一个手机类
public class Phone {    
    public void call(String name) {        
        System.out.println("给" + name + "打电话");    
    }
}

// 创建一个新版本手机类...
public class NewPhone extends Phone {
    
    @Override
    public void call(String name) {
        System.out.println("开启视频功能");
        super.call(name);
  }
}
// 创建测试类
public class Test {
        public static void main(String[] args) {
            Phone p = new Phone();
            p.call("张三");
            NewPhone np = new NewPhone();
            np.call("张三");
             // 输出结果:
             // 给张三打电话
             // 开启视频功能
             // 给张三打电话
        }
}
2.4、父类引用指向子类对象(多态,向上转型)
  • 即父类的引用地址不仅可以指向父类对象,也可以指向子类对象(多态特性)
public class Parent { /* 父类属性和方法 */ }
public class Child extends Parent { /* 新增功能 */ }

/** 测试类*/
public class Test {
    
     public static void main(String[] args) {
        // 父类引用指向父类对象
        Parent child = new Parent();
        // 创建语法正确
        // Parent父类引用地址实际指向Child子类对象 new Child()
        Parent child = new Child();
    }
}
  • 代码执行时,JVM编译器会根据实际对象类型调用方法(多态,不同的对象呈现不同的行为)
    • 多态必须在继承关系中体现
    • 子类必须对父类中的方法重写
    • 通过父类引用调用子类中重写的方法(JVM编译器会根据实际对象类型调用对应方法,Java中的隐式转换【向上转型】
/** 创建父类Animal */
class  Animal {
    // 定义一个行为特征“吃” 提供子类覆盖重写
    public void eat() {}
}

 /** 创建子类Dog */
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("吃狗粮");
    }
}
/** 创建子类Cat */
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("吃猫粮");
    }
}

/** 测试类*/
public class Test {
    public static void main(String[] args) {
         Animal dog = new Dog();
         dog.eat();
         Animal cat = new Cat();
         cat.eat();
         // 输出结果:
         // 吃狗粮
         // 吃猫粮
    }
}
  • 父类引用无法访问子类独有方法,如果需要访问子类独有方法,需要强制类型转换(向下转型)
/** 创建父类Animal */
class  Animal {}

 /** 创建子类Dog */
class Dog extends Animal {
    public void wang() {
        System.out.println("汪汪汪");
    }
}
 
/** 测试类*/
public class Test {
    public static void main(String[] args) {
         Animal dog = new Dog();
         dog.wang(); // 编译错误!父类引用无法访问子类特有方法
         // 强制类型转换
         ((Dog) dog).wang(); // 正确
    }
}

三、Java继承的特点总结(补充)

  1. final继承限制:被final修饰的类/方法不可继承,重写
    1. final是Java的一种修饰符,可以用来修饰类,变量,属性,方法
    2. final修饰的变量命名最好大写(规范)
    3. final修饰方法时,该方法不可被重写
    4. final修饰属性时,该属性字段值不可被修改(常量字段)
    5. final修饰类时,该类不可被继承,通常这个类被称为封装类
  2. 业务需求需要多继承时,可通过接口类实现
  3. 访问控制符限制
    1. private成员不可被子类继承(不能直接继承),子类中也无法直接使用访问,通常会封装Get和Set方法访问
    2. protected专为继承设计,仅供子类访问
    3. default默认修饰符,在同一个包下可以访问
  4. 继承中构造函数的继承特点
    1. 因为子类会使用父类的属性和函数,所以在子类创建时,会先初始化创建父类。
    2. 子类构造中没有显示调用父类构造函数时,子类会默认访问父类的无参构造函数(隐式调用)
    3. 每个类在创建的时候默认有一个无参构造函数(隐式创建),当类中显式创建构造函数时,默认的无参构造函数会失效,子类在创建时如果没有找到父类对应的构造函数,根据具体编码情况,可能会出现代码行报错,或编译出错。
      1. 父类没有无参构造函数,子类构造函数中没有使用super显式调用父类其他构造函数时,会出现编译报错:找不到父类的无参构造函器。
  5. 方法重写和方法重载的异同
    1. 方法重载在同一个类中实现,方法同名,参数列表不同返回值类型可以不同
    2. 方法重写在父子类中实现,方法同名,参数列表相同,返回值类型必须相同,或是返回类型的子类
    3. 重写的方法需要用@Override修饰
    4. 重写方法不能缩小被重写方法的访问权限。
  6. 父子类继承时,代码初始化顺序
    1. 执行父类静态代码块{},子类静态代码块{}
    2. 执行父类实例代码块,父类构造方法
    3. 执行子类实例代码块,子类构造方法
    4. 最终子类实例化对象时,父类和子类的静态代码块不再执行

四、结语

这篇文档仅讨论Java继承的语法基础和理论基础,不涉及继承的实际应用场景。在实际业务场景中,继承几乎成为每个开发者的习惯,作为初学者需要多多代码实践,反复练习。

Java继承在实际业务场景中的代码案例可以参考下方蓝色字体链接

02.Java继承在实际业务场景中的应用【代码案例】-CSDN博客

如果以后功成名就,会不会感谢此刻苦熬技术文档的你?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星夜温蓝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值