• (JavaSE)继承和多态


    继承

    继承:对共性的抽取,实现代码的复用
    在这里插入图片描述
    可以把狗和猫这两个类中姓名,年龄,吃饭这些共同部分抽取出来,组成一个新的类

    在这里插入图片描述
    子类可以继承父类的成员属性和方法
    子类也叫派生类
    父类也叫基类,超类

    子类要体现自己特有的属性

    继承不要超过3层

    父类成员访问

    访问同名成员属性

    class Base{
        int a;
        int b;
    }
    public class Derived extends Base {
        int a;
        int c;
        public void method(){
            a=10;
            b=20;
            c=30;
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
        }
    
        public static void main(String[] args) {
            Derived derived=new Derived();
            derived.method();
            Base base=new Base();
            System.out.println(base.a);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    10//子类的a
    20
    30
    0//父类的a
    
    • 1
    • 2
    • 3
    • 4

    当子类和父类中有同名的成员变量时,优先访问子类(就近原则)

    在子类中访问子类父类同名的成员属性,如果想访问父类的
    super
    在这里插入图片描述
    输出结果:null正在看家护院!

    在这里插入图片描述

    访问同名成员方法

    public class Base {
    public void methodA(){
    System.out.println("Base中的methodA()");
    }
    }
    public class Derived extends Base{
    public void methodA(int a) {
    System.out.println("Derived中的method(int)方法");
    }
    }
    public void methodC(){
    methodA(); // 没有传参,访问父类中的methodA()
    methodA(20); // 传递int参数,访问子类中的methodA(int)
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在子类方法中或通过子类对象访问方法时,当子类和父类存在同名的成员方法时,如果构成重载,则根据调用的方法的参数列表访问相对应的方法

    在这里插入图片描述

    说明重载可以发生在两个不同的类

    每一个类都会生成自己的字节码文件

    Java中只能继承一个类

    super关键字

    super.data 访问父类的普通成员变量
    super.func()调用父类的普通成员方法
    super()调用父类的构造方法
    super只能在非静态方法中使用

    子类构造方法

    当我们没写构造方法时,编译器会默认给一个不带参数的构造方法。
    子类构造对象时,要先调用父类的构造方法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    虽然调用了父类的构造方法,但是没有生成父类的对象,只是帮助子类初始化从父类继承的属性

    在这里插入图片描述
    在这里插入图片描述

    public class Test {
        public static void main(String[] args) {
            Dog dog=new Dog("hello",5,false);
            System.out.println("==============================");
            Cat cat=new Cat();
            System.out.println("==============================");
            Dog dog2=new Dog("hello",5,false);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    Animal::static{}
    Dog::static{}
    Animal::{}
    Animal(String , int)
    Dog::{}
    Dog(String , int ,boolean)
    ==============================
    Cat::static{}
    Animal::{}
    Animal(String , int)
    Cat::{}
    Cat()
    ==============================
    Animal::{}
    Animal(String , int)
    Dog::{}
    Dog(String , int ,boolean)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    静态代码块只会执行一次

    protected关键字

    在这里插入图片描述

    package demo1;
    
    public class TestDemo {
        protected int a=10;
    
        public void func(){
            System.out.println(a);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    package 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();                   //10
            //System.out.println(t.a);    //10
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    说明不同包的子类可以访问

    注:外部类的修饰符只有public或default,因为外部类的上一级是包,所以外部类的作用域是同一包和任何位置

    在这里插入图片描述

    继承与组合

    继承: is a
    组合: has a

    class Student{
    
    }
    class Teacher{
    
    }
    class School{
        public Student[] students;
        public Teacher[] teachers;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Student , Teacher这两个类的实例是School这个类的字段

    多态

    多态的条件:继承,向上转型,重写

    重写

    在这里插入图片描述

    重写和重载的区别

    在这里插入图片描述

    静态绑定和动态绑定

    静态绑定(早绑定):根据传入的参数决定调用哪个方法
    编译时就确定好调用哪个方法。

    public static void function(){
    
        }
        public static void function(int a){
    
        }
        public static void function(int a,int b){
    
        }
    
        public static void main(String[] args) {
            
            function();
            function(10);
            function(10,20);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    动态绑定(晚绑定):
    运行时才确定好调用哪个方法。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    向上转型

    直接赋值

    public class Test {
        public static void main2(String[] args) {
            //1.直接赋值
            Dog dog=new Dog("hello",5,false);
            Animal animal1=dog;
            Animal animal2=new Cat("hello",5);
            animal1.eat();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    方法传参

    在这里插入图片描述

    方法返回

    public class Test {
        public static Animal function2(){
            return new Cat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    向下转型

    public static void main(String[] args) {
            Animal animal=new Cat("hhh",3);
            Cat cat=(Cat)animal;//向下转型
            cat.catchMouse();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    多态的优缺点

    多态的好处:降低代码的"圈复杂度"。
    圈复杂度:一段代码中条件语句和循环语句出现的个数

    class Shape{
        public void draw(){
            System.out.println("画图形!");
        }
    }
    class Rect extends Shape{
        @Override
        public void draw() {
            System.out.println("画矩形!");
        }
    }
    class Cycle extends Shape{
        @Override
        public void draw() {
            System.out.println("画圆!");
        }
    }
    class Flower extends Shape{
        @Override
        public void draw() {
            System.out.println("画❀!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    如果我想要实现画一个圆,一个矩形,一个圆,一个矩形,一个花

    不用多态,这样实现

    public static void drawShapes(){
            String[] strings={"cycle","rect","cycle","rect","flower"};
            for (String x:
                 strings) {
                if(x.equals("cycle")){
                    Cycle cycle=new Cycle();
                    cycle.draw();
                }else if(x.equals("rect")){
                    Rect rect=new Rect();
                    rect.draw();
                }else {
                    Flower flower=new Flower();
                    flower.draw();
                }
            }
        }
    
        public static void main(String[] args) {
            drawShapes();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用多态:

    public static void drawShapes(){
            Shape[] shapes={new Cycle(),new Rect(),new Cycle(),new Rect(),new Flower()};
            for (Shape s:
                 shapes) {
                s.draw();
            }
        }
       public static void main(String[] args) {
            drawShapes();
        } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ⭐⭐⭐⭐⭐⭐⭐分割线⭐⭐⭐⭐⭐⭐⭐⭐

    class B {
        public B() {
            func();
        }
    
        public void func() {
            System.out.println("B.func()");
        }
    }
    
    class D extends B {
        private int num = 1;
    
        @Override
        public void func() {
            System.out.println("D.func() " + num);
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            D d = new D();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    输出结果

    D.func() 0
    
    • 1

    分析:构造D对象,调用父类B的构造方法,而B的构造方法内调用了重写的func方法,由于动态绑定,调用重写的子类方法,此时子类D还没有开始构造,num的值未初始化是0

    得出结论:构造方法内部尽量只使用final,static方法,防止重写

  • 相关阅读:
    Python真的是白学了
    xargs 命令详解
    Python 多线程、线程池、进程池
    Java面试题每日问题
    红队技术笔记
    Synchronized 关键字
    我认识Handler又多了一点点...
    MySQL 常用函数
    数字时代安全风险防范与保密科技创新
    项目实战:修改水果库存系统特定库存记录
  • 原文地址:https://blog.csdn.net/qq_63983125/article/details/126260464