继承性

  • 子类(也称为派生类)继承父类(也称为基类),子类就获取到了父类中声明的所有属性和方法(构造方法不能继承,只能在子类构造方法第一行调用父类的构造方法)。但是由于封装性的影响,可能子类不能直接调用父类中的属性和方法(如父类中声明为private)。继承提高了代码的复用性

  • 子类继承父类后,可以扩展自己的属性和方法。继承的出现更有利于功能的扩展

  • 子类继承父类后,还可以重写方法,也叫方法的覆盖,覆盖是指派生类中存在重新定义的函数,其与父类中的某个函数(函数名、参数列表、返回值类型)都相同,那么当派生类对象调用该函数时,会自动调用子类中的覆盖版本。不过要注意:实现方法覆盖时,子类方法不能比父类的方法权限小,子类方法抛出的异常不能比父类多。注意方法覆盖与方法重载的不同

super 关键字

结论:

  • Java构造器不是函数,所以不能被继承,只能在子类构造方法第一行通过使用super来调用父类的构造方法。

  • 如果父类中有显式无参构造函数或者默认无参构造函数时,子类中的构造函数的方法体中会默认调用父类无参构造函数。当然,以上情况下我们也可以自行在子类构造函数中通过super()来显式调用父类无参构造函数或通过super(参数)来显式调用父类有参构造函数。但是,当父类中仅有有参构造函数时,那么子类构造函数中必须由我们手动通过super(参数)来显式调用,否则运行时会报错。

以下由两段代码用于解释:

😄

//父类
public class Person {
    public String name;
    public Person(){
        System.out.println("Person222");
    }
    public Person(int a){
        System.out.println("Person333");
    }
}

//测试
public class Main {
    public static void main(String[] args) {
        Student s1=new Student(110);
        System.out.println(s1.sid);
    }
}

//子类1如下,测试结果为Person222以及110
public class Student extends Person{
    public int sid;
    public Student(int n){
        super();//根据上述解释,这里不写的话也会默认调用,输出结果一样
        this.sid=n;
    }
}
//子类2如下,测试结果为Person333以及110
public class Student extends Person{
    public int sid;
    public Student(int n){
        super(n);//根据上述解释,这里可以显示调用父类有参构造函数
        this.sid=n;
    }
}

😄

//父类
public class Person {
    public String name;
    public Person(int a){
        System.out.println("Person333");
    }
}

//测试
public class Main {
    public static void main(String[] args) {
        Student s1=new Student(110);
        System.out.println(s1.sid);
    }
}

//子类如下:测试结果为Person333以及110
public class Student extends Person{
    public int sid;
    public Student(int n){
        super(n);//根据上述解释,由于父类中仅有有参构造函数,所以这里必须显示调用父类有参构造函数,否则出错
        this.sid=n;
    }
}

方法覆盖-向上转型

结论:

  • 实例变量、静态变量、静态方法在编译期间就已经静态绑定了,而普通方法实行的是动态绑定。当调用参数或方法时,参数和静态方法会根据当前声明的类型去调用声明对象对应的成员,而普通方法会根据实际创建的对象类型去调用相应的方法。
  • 父类引用指向子类对象,上转型,父类引用无法对子类新增成员变量和新增方法进行操作和使用。

以下代码用于解释:

😄

//父类
public class Person {
    String name="fathername";
    static String sex="staticfathersex";
    public void say(){
        System.out.println("fathersay");
    }
    public static void staticsay(){
        System.out.println("staticfathersay");
    }
}
//子类
public class Student extends Person{
    String name="sonname";
    static String sex="staticsonsex";
    public void say(){
        System.out.println("sonsay");
    }
    public static void staticsay(){
        System.out.println("staticsonsay");
    }
    String age="11岁";
    public void getAge(){
        System.out.println("刚满11岁");
    }
}
//测试,由上述解释可得以下测试结果
public static void main(String[] args) {
        Person s1=new Student();//父类引用指向子类
        System.out.println(s1.name);//fathername
        System.out.println(s1.sex);//staticfathersex
        s1.staticsay();//staticfathersay
        s1.say();//sonsay
    	
    	System.out.println(s1.age);//报错
    	s1.getAge();//报错
}

小tips:

  • Java中声明的所有类,如果没有显式地声明其父类是,默认继承了Object类。

  • Java支持多层继承,但不支持多重继承。

  • 继承的本质是对一批类的进一步抽象。