JAVA继承

目录

概念

1、super关键字

2、继承关系上的执行顺序

3、protected 关键字

4、继承与接合

5、final 关键字


概念

理解

将相同的属性和方法提出来构成一个方法 然后可以被继承

子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

内容

1、this会优先访问子类自己的,如果子类没有,访问的就是父类的

2、super只是一个关键字,在代码层面上,能够达到易读的效果。只访问父类的

3、此时虽然执行了父类的构造方法,但是并没有生成父类的对象,这里只是帮助子类初始化从父类继承过来的属性。

注意:

  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构 造方法
  2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的 父类构造方法调用,否则编译失败。
  3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
  4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现

代码

class Animal{
    public String name;
    public int age;

    public Animal(String name,int age)//父类构造方法
    {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println(name+"吃饭");
    }
}

class Dog1 extends Animal{
    // 傻 是狗1的特殊属性
    public boolean silly;

    //有参数要自己显性构造方法
    public Dog1(String name,int age,boolean silly){
        super(name,age);//必须在第一行,先帮父类部分初始化
        this.silly = silly;
    }
    public void houseGuard(){
        System.out.println(super.name+"正在看家护院");
        System.out.println(name+"正在看见护院");
    }
}

/*class Cat extends Animal{
    // 猫特有的行为
    public void catchMouse(){
        System.out.println(name+"抓老鼠");
    }
}*/

public class TestAnimal {
    public static void main(String[] args) {
        Dog1 dog = new Dog1("xiao",18,false);
        //Cat cat = new Cat();

    }
}


1、super关键字

理解

  1. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  2. 在构造方法中:super用于调用父类构造方法,不能同时与this在构造方法中出现  

  3. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加

内容

Dog1 dog = new Dog1("xiao",18,false);

带参数的构造需要自己创建构造函数

创建Dog1对象的时候会调用

    public Dog1(String name,int age,boolean silly){
        super(name,age);//必须在第一行,先帮父类部分初始化
        this.silly = silly;
    }

super可以理解成调用

    public Animal(String name,int age)//父类构造方法
    {
        this.name = name;
        this.age = age;
    }

代码

class Animal{
    public String name;
    public int age;

    public Animal(String name,int age)//父类构造方法
    {
        this.name = name;
        this.age = age;
    }
}

class Dog1 extends Animal{
    // 傻 是狗1的特殊属性
    public boolean silly;

    //有参数要自己显性构造方法
    public Dog1(String name,int age,boolean silly){
        super(name,age);//必须在第一行,先帮父类部分初始化
        this.silly = silly;
    }
    // 狗的特有行为
    public void houseGuard(){
        System.out.println(super.name+"正在看家护院");
        System.out.println(name+"正在看见护院");
    }
}

public class TestAnimal {
    public static void main(String[] args) {
        Dog1 dog = new Dog1("xiao",18,false);

    }
}

2、继承关系上的执行顺序

理解

静态——实例——构造

内容

结论:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行

2、父类实例代码块和父类构造方法紧接着执行

3、子类的实例代码块和子类构造方法紧接着再执行

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

注意:

  1. 静态代码块先执行,并且只执行一次,在类加载阶段执行
  2. 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行

代码

class Person {
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        
        System.out.println("1:Person:构造方法执行");
    }

    {
        System.out.println("2:Person:实例代码块执行");
    }

    static {
        System.out.println("3:Person:静态代码块执行");
    }
}
class Student extends Person{
    public Student(String name,int age) {
        super(name,age);
        System.out.println("4:Student:构造方法执行");
    }

    {
        System.out.println("5:Student:实例代码块执行");
    }
    
    static {
        System.out.println("6:Student:静态代码块执行");
    }
}
public class TestDemo4 {
    public static void main(String[] args) {
        Student student1 = new Student("张三",19);
        System.out.println("===========================");
        Student student2 = new Student("李四",20);


   //代码输出为:14 2356

3、protected 关键字

理解

可在不同包的子类里调用

JAVA继承_第1张图片

 

内容

注意:父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

代码

package demo1;//在demo1下的同一类

public class TestDemo {
    protected int a = 10;//a被protected修饰
    public void func(){
        System.out.println(a);
    }
}

package demo1;//在demo1下的不同类

public class TestDemo2 {
    public static void main(String[] args) {
        TestDemo testDemo = new TestDemo();
        System.out.println(testDemo.a);
    }
}

package demo2;//在demo2不同包的子类
import demo1.TestDemo;
//不同包的子类
public class Test extends TestDemo {
    public void test(){
        System.out.println(super.a);
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.test();
    }
}


4、继承与接合

理解

继承:可以看做 是 is - a的关系 class Dog extends Animal Dog is a Animal
组合:a part of / has-a 的关系 学生和老师 是学校的一部分 学校有学生和老师

内容

 

组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合。

代码

// 轮胎类
class Tire{
// ...
} // 发动机类
class Engine{
// ...
} // 车载系统类
class VehicleSystem{
// ...
}
class Car{
    private Tire tire; // 可以复用轮胎中的属性和方法
    private Engine engine; // 可以复用发动机中的属性和方法
    private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
} // 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}

5、final 关键字

理解

final关键可以用来修饰变量、成员方法以及类。

内容

  1. 修饰变量或字段,表示常量(即不能修改)
  2. 修饰类:表示此类不能被继承 String 字符串类, 就是用 final 修饰的, 不能被继承. 

  3. 修饰方法:表示该方法不能被重写
     

代码

final int a = 10;  
a = 20; // 编译出错  

final public class Animal {
...
}
public class Bird extends Animal {
...
} 
// 编译出错Error:(3, 27) java: 无法从最终com.bit.Animal进行继

 

你可能感兴趣的:(JAVA,java,jvm,开发语言)