• Java继承与多态


    目录

    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关键字

    1. class Animal {
    2. public String name;
    3. public int age;
    4. public void eat() {
    5. System.out.println(name + "正在吃饭");
    6. }
    7. private int hehe;
    8. }
    9. // 子类 继承 父类
    10. class Dog extends Animal {
    11. public void dack() {
    12. System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    13. }
    14. }

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

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

    1. class Animal {
    2. public String name;
    3. public int age;
    4. public void eat() {
    5. System.out.println(name + "正在吃饭");
    6. }
    7. private int hehe;
    8. }
    9. // 子类 继承 父类
    10. class Dog extends Animal {
    11. public void dack() {
    12. System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    13. }
    14. }
    15. public class Test {
    16. public static void main(String[] args) {
    17. Dog dog = new Dog();
    18. dog.name = "旺财";
    19. dog.age = 10;
    20. //dog.hehe = 100; //父类中的私有权限不可以直接访问 可以通过对外接口的方式
    21. dog.eat();
    22. dog.dack();
    23. }
    24. }

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

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

    1. class Animal {
    2. public String name = "haha";
    3. public int age;
    4. public void eat() {
    5. System.out.println(name + "正在吃饭");
    6. }
    7. private int hehe;
    8. }
    9. class Dog extends Animal {
    10. public String name = "hehe";
    11. public void dack() {
    12. System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
    13. }
    14. }
    15. public class Test {
    16. public static void main(String[] args) {
    17. Dog dog = new Dog();
    18. System.out.println(dog.name);
    19. }
    20. }

    这时的打印是hehe

    1.3 super关键字

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

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

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

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

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

    1. class Animal1 {
    2. public String name;
    3. public int age;
    4. public Animal1() {
    5. }
    6. public Animal1(String name, int age) {
    7. this.name = name;
    8. this.age = age;
    9. System.out.println("Animal1(String ,int )");
    10. }
    11. public void eat() {
    12. System.out.println(name + " 吃饭 ");
    13. }
    14. public static void staticEat() {
    15. System.out.println("父类静态方法");
    16. }
    17. }
    18. /**
    19. * super
    20. * super. 在子类中可以调用 父类普通成员 变量
    21. * super. 在子类方法中可以调用 父类普通成员 方法
    22. * super() 调用父类构造方法
    23. */
    24. class Dog1 extends Animal1 {
    25. public boolean still;
    26. public String name = "hello";
    27. //调用子类的构造方法要先调用父类的构造方法
    28. //不构造会默认给一个super()
    29. public Dog1(String name, int age, String name1, boolean still) {
    30. super(name, age);
    31. this.name = name1;
    32. this.still = still;
    33. }
    34. public void func() {
    35. super.staticEat();//不建议用super调用父类的静态方法
    36. System.out.println(super.name + " " + age + " " + name + " " + still);
    37. }
    38. }

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

    调用顺序为 
    先静态,后实例,再构造
    在继承中会先将父类的实例和构造调用完,再调用子类的实例和构造
    1.父类的静态 2.子类的静态 
    3.父类的实例 4.父类的构造 
    5.子类的实例 6.子类的构造
    
    1. package inherit;
    2. /**
    3. * 调用顺序为
    4. * 1.父类的静态 2.子类的静态
    5. * 3.父类的实例 4.父类的构造
    6. * 5.子类的实例 6.子类的构造
    7. */
    8. class Animal1 {
    9. public String name;
    10. public int age;
    11. public Animal1() {
    12. }
    13. static {
    14. System.out.println("Animal1::static{}");
    15. }
    16. {
    17. System.out.println("Animal1::{}");
    18. }
    19. public static void staticEat() {
    20. System.out.println("父类静态方法");
    21. }
    22. }
    23. class Dog1 extends Animal1 {
    24. public boolean still;
    25. public String name = "hello";
    26. static {
    27. System.out.println("Dog1::static{}");
    28. }
    29. {
    30. System.out.println("Dog1::{}");
    31. }
    32. }
    33. public class Test2 {
    34. public static void main(String[] args) {
    35. Dog1 dog1 = new Dog1("hello", 10, "heihei", false);
    36. }
    37. }

    输出的顺序则是:

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

    1.5 继承方式

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

    1.6 final关键字

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

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

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

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

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

    2.多态

    2.1 重写

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

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

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

    1. class Animal00 {
    2. public String name;
    3. public int age;
    4. public void eat() {
    5. System.out.println(name + " 吃饭 ");
    6. }
    7. }
    8. /**
    9. * 子类Dog00中的eat()方法是 父类Animal00类中eat()方法的重写
    10. * 父类中被private限定符修饰的不可以被重写
    11. * 重写的方法的范围一定要大于等于重写前方法的范围
    12. * 但是不能对呗 final 或者 static 修饰的方法以及 构造方法 进行重写
    13. */
    14. class Dog00 extends Animal00 {
    15. public boolean still;
    16. public String name;
    17. public void eat() {
    18. System.out.println(name + "正在吃狗粮");
    19. }
    20. }

    2.2 向上转型和向下转型

    2.2.1 向上转型

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

    Animal00 animal = new Dog00();

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

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

    在代码运行时,当传递不同类对象时,会调用对应类中的方法。
    1. public static void function(Animal00 animal) {
    2. animal.eat();
    3. }
    4. public static void main(String[] args) {
    5. //向上转型 小范围向大范围转换
    6. Animal00 animal = new Dog00("哈士奇", 10, "德牧", false);
    7. function(animal);
    8. Cat00 cat = new Cat00("咪咪", 20);
    9. Animal00 animal1 = cat;
    10. function(animal1);
    11. }

    2.2.2 向下转型

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

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

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

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

    右边不是子类则返回false

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

    这样提高了代码的安全性

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

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

  • 相关阅读:
    程序员的浪漫
    MVC架构_Qt自己的MV架构
    大一新生HTML期末作业,网页制作作业——海鲜餐饮网站登录页面(单页面)HTML+CSS+JavaScript
    VUE~富文本简单使用~tinymce
    【Java】对象处理流(ObjectOutputStream和ObjectInputStream)
    EtherCAT 总线型 4 轴电机控制卡解决方案
    【Linux】shell命令行简单解释器
    SpringBoot+SpringCloud面试总结都在这里
    MySQL添加、查看、修改与删除数据
    2023年,想要靠做软件测试获得高薪,还有机会吗?
  • 原文地址:https://blog.csdn.net/m0_64318128/article/details/126811972