java继承详解

Java 继承详解 | 菜鸟教程 (runoob.com)
Java 继承 | 菜鸟教程 (runoob.com)

什么是继承?

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

多个类可以称为子类,单独这个类称为父类超类或者基类。使用extends关键词

class 父类 {
}
 
class 子类 extends 父类 {
}

继承之后,子类自动拥有父类的属性与方法(一般,有部分特殊情况)

继承的特点

1.Java只支持单继承,不支持多继承。

//一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error

2.Java支持多层(重)继承(继承体系)。

class A{}
class B extends A{}
class C extends B{}

super,this关键字

super是一个关键字,代表父类的存储空间标识。(可以理解为父亲的引用)
super和this的用法相似,可以用来在子类中访问父类的元素

注意:

  1. 不能访问父类private修饰的属性与方法
  2. 可以访问父类构造器
  3. super,this的访问遵循逐级向上查找,就近原则(下文链接中会提到)

继承注意事项

访问修饰符

子类拥有父类非 private 的属性、方法。
子类不能访问父类中由private修饰的属性与方法

java.lang.object

所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object(这个类在 java.lang 包中,所以不需要 import)祖先类。

final关键字
修饰类
  • final类:一旦一个类被声明为final,它就不能被继承。这意味着你不能创建该类的子类。例如:
    final class MyFinalClass {
        // 类的方法和变量
    }
    
修饰方法
  • final方法:一旦一个方法被声明为final,它就不能被重写(override)。这意味着子类不能改变该方法的行为。例如:
    public class MyClass {
        public final void myFinalMethod() {
            // 方法体
        }
    }
    
修饰变量
  • final成员变量:一旦一个成员变量被声明为final,它的值就不能被改变。这意味着你必须在声明变量时或构造函数中为其赋值。例如:
    public class MyClass {
        private final int myFinalVariable;
        public MyClass(int value) {
            myFinalVariable = value;
        }
    }
    
  • final局部变量:在方法内部,你可以声明一个final局部变量,这意味着在方法内部,该变量的值不能被改变。例如:
    public void myMethod() {
        final int myFinalLocalVariable = 10;
        // myFinalLocalVariable的值不能被改变
    }
    
构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

class SuperClass {
    private int n;
 
    // 无参数构造器
    public SuperClass() {
        System.out.println("SuperClass()");
    }
 
    // 带参数构造器
    public SuperClass(int n) {
        System.out.println("SuperClass(int n)");
        this.n = n;
    }
}
 
// SubClass 类继承
class SubClass extends SuperClass {
    private int n;
 
    // 无参数构造器,自动调用父类的无参数构造器
    public SubClass() {
        System.out.println("SubClass()");
    }
 
    // 带参数构造器,调用父类中带有参数的构造器
    public SubClass(int n) {
        super(300);
        System.out.println("SubClass(int n): " + n);
        this.n = n;
    }
}
 
// SubClass2 类继承
class SubClass2 extends SuperClass {
    private int n;
 
    // 无参数构造器,调用父类中带有参数的构造器
    public SubClass2() {
        super(300);
        System.out.println("SubClass2()");
    }
 
    // 带参数构造器,自动调用父类的无参数构造器
    public SubClass2(int n) {
        System.out.println("SubClass2(int n): " + n);
        this.n = n;
    }
}
 
public class TestSuperSub {
    public static void main(String[] args) {
        System.out.println("------SubClass 类继承------");
        SubClass sc1 = new SubClass();
        SubClass sc2 = new SubClass(100);
 
        System.out.println("------SubClass2 类继承------");
        SubClass2 sc3 = new SubClass2();
        SubClass2 sc4 = new SubClass2(200);
    }
}

所以一般来说父类与子类初始化的顺序是

父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法

方法重写

子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。但是父类的私有方法无法重写。因为父类私有方法,子类看不到,因此父类私有方法的重写也就无从谈起。

覆盖注意事项

  • 覆盖时,子类方法权限一定要大于等于父类方法权限;
  • 静态只能覆盖静态。
  • 参数列表得一样,但是返回类型可以不一样。重写的方法返回类型必须是原方法的子类。例如string 与 object

覆盖的使用场景

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。

继承的内存布局

0293_韩顺平Java_继承本质详解_哔哩哔哩_bilibili
![[Pasted image 20240826192255.png]]

如何通过通过子类访问父类

0293_韩顺平Java_继承本质详解_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值