1、概念
多态:多种形态
-
编译时多态
1、方法重载
2、编译阶段就能确定某个名称的方法有多种形态
3、编译时类型决定了通过当前的引用变量可以访问哪些方法和字段
4、声明变量时指定的类型
1、通过 getClass 方法来获取运行时类型
2、运行期所引用的对象的类型
多态的三个必要条件
-
继承
-
子类重写了父类继承的方法
-
父类引用指向子类对象
2、实现结果
运行期间父类类型的引用变量指向那个子类类型的实例,就调用哪个实例的方法( 了解动态绑定 )
3、示例
package polymorphism;
/**
* 1、体验运行时多态:
* 在运行期间,引用变量 引用了 (指向了) 哪一个子类类型的实例,将来调用方法时就调用哪个实例的方法
*
* 2、编译时类型决定了可以通过 引用变量 来访问哪些字段、调用哪些方法,
* 因为子类重写了父类中的方法,因此父类类型的引用变量可以调用的方法在子类实例中是存在的
*
* 3、了解 动态绑定
*/
public class HumanTest {
public static void main(String[] args) {
Human h = null ; // 声明一个 Human 类型的引用变量 h 并为其赋值为 null
System.out.println( "h=> " + h );
h = new Human(); // Human 类型的引用变量 引用了 (指向了) 一个 Human 实例
System.out.println( "h=> " + h );
h.eat( "鸡腿" );
// 父类类型的引用变量 引用了 (指向了) 子类类型的对象
h = new Sinaean(); // Human 类型的引用变量 引用了 (指向了) 一个 Sinaean 实例
System.out.println( "h=> " + h );
h.eat( "米饭" );
// 父类类型的引用变量 引用了 (指向了) 子类类型的对象
h = new British(); // Human 类型的引用变量 引用了 (指向了) 一个 British 实例
System.out.println( "h=> " + h );
h.eat( "包子" );
// 父类类型的引用变量 引用了 (指向了) 子类类型的对象
h = new India(); // Human 类型的引用变量 引用了 (指向了) 一个 India 实例
System.out.println( "h=> " + h );
h.eat( "火锅" );
}
}
4、强制类型转换
package polymorphism;
/**
* 引用类型的强制类型转换
*/
public class HumanTest3 {
public static void main(String[] args) {
// 父类类型的引用变量 指向 子类类型的对象
Object o = new Sinaean();
// o.eat("藜蒿炒腊肉"); // 变量 o 的 编译时类型 是 Object 其中并没有声明 eat方法
if (o instanceof Human) {
Human h = (Human) o;
h.eat("藜蒿炒腊肉"); // 变量 h 的编译时类型是 Human 其中 有 eat 方法
}
if (o instanceof Sinaean) {
Sinaean s = (Sinaean) o;
((Sinaean) o).taiChi(); // 变量 s 的编译时类型是 Sinaean 其中 有 taiChi 方法
}
}
}
5、final 关键字
-
修饰类时,表示该类为最终的类 不能有子类
-
修饰变量时,变量在初始化之后不可以再次赋值
-
修饰方法时,方法中对于父类可见的方法在子类中不可以重写
package object;
public class Monkey {
//无法重写 从Object 继承过来的 被 final 修饰的 getClass 方法
// public final Class<?> getClass() {
//
// }
public static void main(String[] args) {
Monkey m = new Monkey();
System.out.println(m.getClass());
}
}