(1)概念
在下例代码中 A是B的父类 然后将B创建的实类赋给A类型时 不能使用c.fly();这表示在编译时c的类型为A ,但是c.getClass().getName()的结果却为类型B这表示在运行时c的类型为B
package hello;
class A {//父类A
public void print() {
System.out.println("Hello");
}
}
class B extends A{//子类B
public void fly() {
}
}
public class Hello{ //创建一个类叫做Hello
public static void main(String[] args) {
A c = new B();
//使用c.fly();会报错表示c在编译时是A类型的
System.out.println(c.getClass().getName());//hello.b 表示在运行时c是B类型的
}
}
2.继承层次结构
public static void main(String[] args) {
A c = new B();
//使用c.fly();会报错表示c在编译时是A类型的
System.out.println(c.getClass().getName());//hello.b 表示在运行时c是B类型的
c.print();//Hello
}
对象c在运行时不是类型B吗?为什么可以调类型A的print();的功能?
因为在程序运行中B类中没有print()的功能所以JVM会在B的继承层次结构中查找(前提B必须是一个子类或者是一个子接口),JAM将沿着层次结构向上查找print();的实现并运行它
扩展: 如果B类型对A类型的print();进行方法覆盖,那么在运行时对象c的类型是B就可以直接调用print();功能了,也就不需要JVM进行层次结构向上查找了
以上例子证明Java中对象调用方法的绑定是在运行时,而不是编译时所以也叫后期绑定或者动态绑定。 注意 static和final修饰过的功能是前期绑定的
结论 对象c的状态在编译时是不确定的,是多态的 就像下面例子一样
package hello;
class A {//父类A
public void print() {
System.out.println("Hello");
}
}
class B extends A{//子类B
public void print() {
System.out.println("World");
}
public void fly() {
System.out.println("EASY");
}
}
public class Hello{ //创建一个类叫做Hello
public static void main(String[] args) {
A a;
a = new B();
System.out.println(a.getClass().getName());//hello.B
a.print();//World
B b = (B) a;
b.fly();//EASY
}
}
不过有个简单的方法在进行复杂的类型转换(多的自己都看不过来)时,可以加入a.getClass().getName()帮你判断这个对象在这个运行时间内是什么类型的
(2)多态性实战 在下例代码中对象gereeting的类型取决于你输入的语言
package hello;
import java.util.Scanner;
interface Greeting{
public void greet();
}
class English implements Greeting{
@Override
public void greet() {
System.out.println("Good Day");
}
}
class French implements Greeting{
@Override
public void greet() {
System.out.println("Bonjour");
}
}
public class Hello{ //创建一个类叫做Hello
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String instruction = "what is your chosen language ?";//你选择的语言是什么
Greeting greeting = null;
System.out.println(instruction);
while(true) {
String input = scanner.next();//输入选择语言
if(input.equalsIgnoreCase("English")) {
greeting = new English();
break;
}else if(input.equalsIgnoreCase("French")) {
greeting = new French();
break;
}else {
System.out.println(instruction);
}
}
scanner.close();//关闭流对象
greeting.greet();//输出对应语言的问候语句
System.out.println(greeting.getClass().getName());//最后greeting对象的类型
//取决于你的输入
}
}