Java多态详解
程序员文章站
2024-03-02 12:00:22
...
java多态
多态的出现:
- 父类的引用指向子类的对象
定义格式:父类类型 变量名 = new 子类类型();
- 接口的引用指向遵从接口的实现类对象
定义格式:接口 变量名 = new 实现类();
多态的作用:
- 拓宽方法的参数范围:
- 参数要求是父类,这里可以传入父类或者其子类的对象
- 参数是接口类型,这里可以传入直接或者间接的接口实现类对象
- 拓宽方法的返回值范围:
- 返回值类型要求是父类,这里可以返回父类或者其子类的对象
- 返回值类型是接口,这里可以返回该接口或该接口的实现类对象
多态的成员特点:
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对我做出了鄙视:
这里idea清楚的给出了提示,推荐使用类名直接调用成员变量:也就是用Person.id 调用。也就是说这个id是属于Person类的
这是由于对象自带属性值,变量不会发生Override。下面给出代码证明:
我们可以清楚的看到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注解(这代表着重写)。
那当方法加上了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也给出了鄙视
这里idea清楚的给出了提示,推荐使用类名直接调用成员方法:也就是用Person.sleep()调用。也就是说这个sleep()方法是属于Person类的
总结:
当多态发生时,成员方法,没有发生重写访问的就是父类本身的同名方法
多态的转型:
- 向上转型:
- 使用格式:父类类型 变量名=new 子类类型();
适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
- 向上转型:
- 使用格式:子类类型 变量名=(子类类型) 父类类型的变量;
- 适用场景:当要使用子类特有功能时。(这里的父类类型要求是已经向上转型的子类类型,否则可能会出错)