多态的使用:虚拟方法调用
- 有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法。简称:编译时,看左边;运行时,看右边。
注:对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)
public class PolyTest2 {
public static void main(String[] args) {
Sub s= new Sub();
System.out.println(s.count); //20
s.show();//20
Base b = s;
//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否一样。
System.out.println(b == s); //true
System.out.println(b.count); //10
b.show(); //20
}
}
class Base{
int count=10;
public void show(){
System.out.println(this.count);
}
}
class Sub extends Base {
int count= 20;
public void show() {
System.out.println(this.count);
}
}
- 多态的使用前提:
1:继承性
2:方法的重写(而非重载)
public class InterviewTest1 {
public static void main(String[] args) {
Base base = new Sub();
base.add(1, 2, 3);
//输出sub_1
//接着取消-------1的注释,输出仍为sub_1
//子类中的方法add(int a, int[] arr)看成是对父类中的方法add(int a, int... arr)的重写,add(int a, int b, int c)看成是对父类中方法的重载。
//接着取消-------2的注释,输出变为sub_2
// Sub s = (Sub)base;
// s.add(1,2,3);--------2
}
}
class Base {
public void add(int a, int... arr) {
System.out.println("base");
}
}
class Sub extends Base {
public void add(int a, int[] arr) {
System.out.println("sub_1");
}
// public void add(int a, int b, int c) {
// System.out.println("sub_2");
// }---------1
}
-instanceof 关键字的使用注意点:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类的属性和方法不能调用。
问:如何才能调用子类所特有的属性和方法?
答:使用强制类型转换符,也可称为:向下转型
但是使用强转时,可能出现ClassCastException异常:
Person p=new Man();
Woman wo=(Woman)p;//类型转换异常(编译通过,运行不通过)
instanceof关键字的使用
a instanceof A:判断对象a是否是类A的实例。如果,返回true,如果不是,返回false;
使用情境:为了避免在向下转型时出现ClassCastException异常,我们在进行向下转型之前,先进行 instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
如果a instanceof A返回true,则a instanceof B也返回true。 其中类B是类A的父类。由于这种特性,会出现如下情况:
Person p=new Man();
if(p instanceof Man){
System.out.println("man");
}
if(p instanceof Person){
System.out.println("Person");
}
//上述结果既会打印man,也会打印Person
更甚:
// 编译通过,运行时也通过
Object obj = new Woman();
Person p = (Person)obj;
if(obj instanceof Woman){
System.out.println("obj是Woman的实例");//打印
}
if(obj instanceof Person){
System.out.println("obj也是Person的实例");//打印
}
System.out.println(obj.getClass());//obj的类型为Woman类
p.eat();//输出子类重写的方法:女人少吃,为了减肥。
p.walk();//输出子类重写的方法:女人,窈窕的走路。
System.out.println(p.getClass());//p的类型同样为Woman类
// p.goshopping();//报错
这种情况,在重写equals()方法时就有问题
例如:下面的代码中输入为MyDate类的子类
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof MyDate){
MyDate myDate = (MyDate)obj;
return this.day == myDate.day && this.month == myDate.month &&
this.year == myDate.year;
}
return false;
}