Java继承与多态

发布于:2022-12-21 ⋅ 阅读:(137) ⋅ 点赞:(0)

目录

1.继承

1.1 继承的语法

1.2 子类中与父类重名成员的访问

1.3 super关键字

1.4 子类与父类中代码块和构造方法的执行顺序

1.5 继承方式

1.6 final关键字

2.多态

2.1 重写

2.2 向上转型和向下转型

2.2.1 向上转型

2.2.2 向下转型

2.3 避免在构造方法中调用重写方法


1.继承

1.1 继承的语法

类与类之间的继承用extends关键字

class Animal {
    public String name;
    public int age;

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

    private int hehe;
}

//    子类   继承    父类
class Dog extends Animal {
    public void dack() {
        System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    }
}

上面的代码是Dog类继承了Animal类

子类继承父类之后,会将父类的所有属性和方法都继承过来,但是父类中被private修饰的成员不可以直接访问

class Animal {
    public String name;
    public int age;

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

    private int hehe;
}

//    子类   继承    父类
class Dog extends Animal {
    public void dack() {
        System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "旺财";
        dog.age = 10;
        //dog.hehe = 100; //父类中的私有权限不可以直接访问 可以通过对外接口的方式
        dog.eat();
        dog.dack();
    }
}

1.2 子类中与父类重名成员的访问

子类中如果有成员和父类的成员重名,那么在调用时不会调用父类的成员,会优先调用子类的成员

class Animal {
    public String name = "haha";
    public int age;

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

    private int hehe;
}
class Dog extends Animal {
    public String name = "hehe";
    public void dack() {
        System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.name);
    }
}

这时的打印是hehe

1.3 super关键字

如果我们想在子类方法中调用父类的重名成员就要用super关键字。

调用父类的普通成员变量和方法直接用 super. 即可

当调用父类的构造方法是则要用到super(...)

在调用子类的构造方法时,需要先调用父类的构造方法

调用方法就是super() 括号里面进行传参,并且super()必须在子类构造方法的第一条语句,如果子类的构造方法里没有写super(),那么编译器会默认生成一个空的super()

class Animal1 {
    public String name;
    public int age;

    public Animal1() {

    }
    public Animal1(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal1(String ,int )");
    }

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

    public static void staticEat() {
        System.out.println("父类静态方法");
    }
}

/**
 * super
 * super.  在子类中可以调用 父类普通成员 变量
 * super.  在子类方法中可以调用 父类普通成员 方法
 * super() 调用父类构造方法
 */
class Dog1 extends Animal1 {

    public boolean still;
    public String name = "hello";

    //调用子类的构造方法要先调用父类的构造方法
    //不构造会默认给一个super()
    public Dog1(String name, int age, String name1, boolean still) {
        super(name, age);
        this.name = name1;
        this.still = still;
    }
    public void func() {

        super.staticEat();//不建议用super调用父类的静态方法

        System.out.println(super.name + "  " + age + "  " + name + "  " + still);
    }

}

1.4 子类与父类中代码块和构造方法的执行顺序

调用顺序为 
先静态,后实例,再构造
在继承中会先将父类的实例和构造调用完,再调用子类的实例和构造
1.父类的静态 2.子类的静态 
3.父类的实例 4.父类的构造 
5.子类的实例 6.子类的构造
package inherit;

/**
 * 调用顺序为
 * 1.父类的静态 2.子类的静态
 * 3.父类的实例 4.父类的构造
 * 5.子类的实例 6.子类的构造
 */

class Animal1 {
    public String name;
    public int age;

    public Animal1() {

    }

    static {
        System.out.println("Animal1::static{}");
    }

    {
        System.out.println("Animal1::{}");
    }
    public static void staticEat() {
        System.out.println("父类静态方法");
    }
}
class Dog1 extends Animal1 {

    public boolean still;
    public String name = "hello";
    static {
        System.out.println("Dog1::static{}");
    }

    {
        System.out.println("Dog1::{}");
    }

}

public class Test2 {
    public static void main(String[] args) {
        Dog1 dog1 = new Dog1("hello", 10, "heihei", false);
    }
}

输出的顺序则是:

Animal1::static{}
Dog1::static{}
Animal1::{}
Animal1(String ,int )
Dog1::{}
Dog1(String ,int ,String ,boolean )

1.5 继承方式

Java中的继承,可以将父类继承给多个子类,但是一个子类只能继承一个父类,不可以进行多继承,如果想继承多个类,可以让继承的父类去继承其他类。

1.6 final关键字

final可以修饰变量,方法,类

被final修饰的变量,表示为常量,不可以再被修改

被final修饰的方法不可以被重写(多态会说明重写)

被final修饰的类不可以被继承

//此时Animal类将不能被继承
public final class Animal {
...
}

2.多态

2.1 重写

父类中的方法在子类中被重新实现,称为重写

所谓重写,是将父类方法的外壳保存,只将里面的内容进行修改

被重写的方法不可以是构造方法 也不可以是被static、final、private修饰的方法,且重写后的方法,其使用权限一定是  大于等于  重写前的方法的。

class Animal00 {
    public String name;
    public int age;
    public void eat() {
        System.out.println(name + " 吃饭 ");
    }
}

/**
 * 子类Dog00中的eat()方法是 父类Animal00类中eat()方法的重写
 * 父类中被private限定符修饰的不可以被重写
 * 重写的方法的范围一定要大于等于重写前方法的范围
 * 但是不能对呗  final  或者   static  修饰的方法以及 构造方法 进行重写
 */

class Dog00 extends Animal00 {

    public boolean still;
    public String name;
    public void eat() {
        System.out.println(name + "正在吃狗粮");
    }
}

2.2 向上转型和向下转型

2.2.1 向上转型

向上转型是小范围向大范围的转型,也就是子类对象转型成父类对象

Animal00 animal = new Dog00();

父类对象向上转型之后只可以访问父类自己特有的属性和方法,不可以访问子类特有的属性和方法

在被调用子类重写后的方法时,不会调用父类的方法,而是调用子类重写后的方法,这个时候,多态就被体现出来了

在代码运行时,当传递不同类对象时,会调用对应类中的方法。
public static void function(Animal00 animal) {
        animal.eat();
}

public static void main(String[] args) {
        //向上转型 小范围向大范围转换
        Animal00 animal = new Dog00("哈士奇", 10, "德牧", false);
        function(animal);
        Cat00 cat = new Cat00("咪咪", 20);
        Animal00 animal1 = cat;
        function(animal1);
}

2.2.2 向下转型

当子类对象转型成父类对象后,还想调用子类特有的属性,这是要用到向下转型。

public static void main4(String[] args) {
        Animal00 animal = new Cat00("咪咪", 10);
        Cat00 cat = (Cat00) animal;//向下转型
        cat.funcm();//Cat00类特有方法
        cat.eat();//Animal00类的特有方法
    }

但是向下转型是很不安全的,因为如果有多个类继承了同一个父类,那么在转型时可能出现在同属与Animal类的Dog类对象去调用Cat类对象的情况,这是不允许的,所以Java中引入了instanceof

左侧放父类,右边放子类则返回true

右边不是子类则返回false

public static void main5(String[] args) {
        Animal00 animal00 = new Dog00("二哈", 18, "二哈000", true);
        //如果是返回true 不是返回false
        if (animal00 instanceof Cat00) {
            Cat00 cat = (Cat00) animal00;
            cat.funcm();
        }
    }

这样提高了代码的安全性

2.3 避免在构造方法中调用重写方法

因为在调用子类的构造方法时,会先调用父类的构造方法,如果这时在父类的构造方法中调用重写的方法,由于子类对象还没有构造,可能会出现属性未初始化的现象。

本文含有隐藏内容,请 开通VIP 后查看