欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多态详解

程序员文章站 2024-03-02 12:00:22
...

java多态

多态的出现:

  • 父类的引用指向子类的对象
		定义格式:父类类型 变量名 = new 子类类型();
  • 接口的引用指向遵从接口的实现类对象
   		定义格式:接口 变量名 = new 实现类();

多态的作用:

  1. 拓宽方法的参数范围:
 - 参数要求是父类,这里可以传入父类或者其子类的对象

 - 参数是接口类型,这里可以传入直接或者间接的接口实现类对象
  1. 拓宽方法的返回值范围:
- 返回值类型要求是父类,这里可以返回父类或者其子类的对象

- 返回值类型是接口,这里可以返回该接口或该接口的实现类对象

多态的成员特点:

1. 成员变量的特点分析:

 - 当发生多态时,父类的成员变量名和子类相同时, 
 - 我们引用的该成员变量是属于父类还是属于子类的呢?

public class Person {
    public int id = 10;
}

class Student extends Person {
    public int id = 11;
}

class Test {
    public static void main(String[] args) {
    	//多态
        Person person = new Student();
        System.out.println(person.id);
    }
}

System.out.println(person.id);

打印的结果值是10 也就是说这里打印的是父类的成员变量id的值


为了更一步的证明这个结果的正确性,我在Person类的id前加了个static修饰

public class Person {
    public static int id = 10;
}

然后idea对我做出了鄙视:
Java多态详解
这里idea清楚的给出了提示,推荐使用类名直接调用成员变量:也就是用Person.id 调用。也就是说这个id是属于Person类的

这是由于对象自带属性值,变量不会发生Override。下面给出代码证明:
Java多态详解
我们可以清楚的看到person对象没有任何的指向,但是在调用属性值时,idea默认的给出了id的属性
虽然没有给person类对象指向,这段代码会报错,但是我们完全可以证明

对象自带属性值,变量不会发生Override。


2. 成员方法的特点分析:

 - 当发生多态时,父类的成员方法名和子类相同时,  
 - 我们引用的该成员方法是属于父类还是属于子类的呢?  
 - 当用static修饰呢?

public class Person {
    
    public void sleep() {
        System.out.println("人睡觉");
    }

    public void read() {
        System.out.println("人阅读");
    }
}

class Student extends Person {

      @Override
    public void sleep() {
        System.out.println("学生睡觉");
    }

    public void read() {
        System.out.println("人阅读");
    }
}

class Test {
    public static void main(String[] args) {
        Person person = new Student();
        person.sleep();
        person.read();
    }
}

person.sleep(); 学生睡觉
person.read(); 人阅读

我们可以清楚的看出:

  • 在重写方法被调用时(方法上加了@Override),在发生多态的时候调用的是子类的同名方法
  • 当没有发生重写的方法被调用时,(没加@Override)调用的是父类的同名方法

当然这里idea也给出了我浓浓的鄙视,提示我重名方法加@Override注解(这代表着重写)。
Java多态详解


那当方法加上了static呢?结果又会怎样呢

public class Person {

    public  static void  sleep() {
        System.out.println("人睡觉");
    }


}

class Student extends Person {
    @Override
    public static void sleep() {
        System.out.println("学生睡觉");
    }
}

class Test {
    public static void main(String[] args) {
        Person person = new Student();
        person.sleep();
    }
}

person.sleep(); ????
这里运行直接报错了!!!

  • Error:(17, 5) java: 方法不会覆盖或实现超类型的方法
  • 也就是说@Override不能生效

那么我们把@Override去了呢?

class Student extends Person {
    public static void sleep() {
        System.out.println("学生睡觉");
    }
}

person.sleep(); 人睡觉

  • 这里打印的是父类的同名方法

idea也给出了鄙视
Java多态详解
这里idea清楚的给出了提示,推荐使用类名直接调用成员方法:也就是用Person.sleep()调用。也就是说这个sleep()方法是属于Person类的

总结:
当多态发生时,成员方法,没有发生重写访问的就是父类本身的同名方法

多态的转型:

  1. 向上转型:
  • 使用格式:父类类型 变量名=new 子类类型();
    适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
  1. 向上转型:
  • 使用格式:子类类型 变量名=(子类类型) 父类类型的变量;
  • 适用场景:当要使用子类特有功能时。(这里的父类类型要求是已经向上转型的子类类型,否则可能会出错)

综上所述:

        在用多态时要把握好是否 发生重写,发生重写的访问的是子类的属性,否则访问的是父类的属性