总结:
1、编译类型看左边,运行类型看右边
2、属性的值看编译类型
3、方法调用看运行类型
package mypoly;
public class MyPoly {
public static void main(String[] args) {
BB bb = new BB(); // 运行类型是 BB
System.out.println(bb instanceof BB); // true
System.out.println(bb instanceof AA); // true
AA aa = new BB(); // 运行类型是 BB
System.out.println(aa instanceof BB); // true
System.out.println(aa instanceof AA); // true
Object obj = new Object();
System.out.println(obj instanceof AA); // false
String str = "hello";
// System.out.println(str instanceof obj); // 编译报错
}
}
class AA{}
class BB extends AA{}
package mypoly.polydetail;
public class Animal {
public void eat(){
System.out.println("吃");
}
public void sleep(){
System.out.println("睡");
}
public void run(){
System.out.println("跑");
}
public void say(){
System.out.println("Hi~");
}
}
//
package mypoly.polydetail;
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void cathMouse(){
System.out.println("猫抓老鼠");
}
}
//
package mypoly.polydetail;
public class Dog extends Cat{
}
//
package mypoly.polydetail;
public class Test {
public static void main(String[] args) {
// 向上转型: 父类的引用指向了子类的对象
Animal animal = new Cat();
// Object obj = new Cat(); //可以编译通过 Object也是Cat的父类
// 可以调用父类中的成员(访问范围内) 但不能调用子类的特有成员
// animal.catchMouse(); // 报错 编译阶段能调用哪些成员 由编译类型决定
// 最终运行效果看子类中的具体实现 调用方法时 从子类的成员中开始查找调用 规则与继承一致
animal.eat();
animal.run();
animal.sleep();
animal.say();
// 向下转型
Cat cat = (Cat) animal;
cat.cathMouse();
// 要求父类的引用必须指向的是向下转型的目标类型的对象 - 即animal原来本身就是指向Cat的
// 即使 Dog 类继承Cat类,也会运行时报错
// Dog dog = (Dog)animal; // 运行时报错
}
}



