声明:这片博客内容信息来源于书籍<Java编程思想>
Java编程语言有三个基本特征:
1、封装:通过合并特征和行为来创建新的数据类型。
2、继承:采用现有类的形式并在其中添加新代码,可以达到代码复用和使用原有类的属性和方法。
今天的内容是讲多态
所谓多态,就是同一种消息被多个对象接收而表现出不同的行为,前提这多个对象是同一个基类导出。
看下面代码:
public class day01_2 { public static void main(String[] args) { Shape1 shape1 = new Circle1(); shape1.draw(); shape1.fun(); } } class Shape1{ public void draw(){ System.out.println("Shape draw"); } public static void fun(){ System.out.println("Shape fun"); } } class Circle1 extends Shape1{ public void draw(){ System.out.println("Circle draw"); } public static void fun(){ System.out.println("Circle fun"); } }
代码输出结果为
首先我们来了解一下方法的绑定:
将一个方法调用同一个方法主体关联起来被称为绑定,若在程序执行前进行绑定(也就是编译期绑定),叫做前期绑定
例如上面的代码,sh有两个相同的方法draw,它怎么知道到底调用那个方法
解决的方法就是动态绑定,就是在运行时根据对象的类型进行绑定。
这样我们就能理解第一行的输出了,但是为什么第二行的输出是Shape fun呢
这是因为在Java中,除了static和final方法(private方法属于final方法)之外,其他方法都是后期绑定。导致了输出为Shape fun。
多态也是有缺陷的:
缺陷1:覆盖 私有方法
public class day01_3 { private void f() { System.out.println("private f"); } public static void main(String[] args) { day01_3 day01_3 = new Derived(); day01_3.f(); } } class Derived extends day01_3{ public void f(){ System.out.println("public f"); } }
我们所希望的输出是public f,但由于private方法被自动认为是final方法,而且对导出类是屏蔽的。因此,在这种情况下,
Derived的f方法就是一个全新的方法,所以Derived的f方法并不是重载父类的f方法,输出就是public f
结论就是:只有非private方法才可以被覆盖,但还需要密切注意覆盖private方法的现象,虽然编译期不报错,但也不会按照
我么你的期望来执行。
缺陷2:域与静态方法:
一旦你了解多态机制,可能就会认为所有事物都可以多态发生。然而只有普通的方法调用可以是多态的。
例如你直接访问某个域或者静态方法。
public class day01_4 { public static void main(String[] args) { Super s = new Sub(); System.out.println(s.f); s.printf(); } } class Super{ public int f = 0; public static void printf(){ System.out.println("Super f"); } } class Sub extends Super{ public int f = 1; public static void printf(){ System.out.println("Sub f"); } }
它的输出全都是Super类的域和静态方法值,原因就是当Sub对象转型为Super,任何域访问操作都将由编译期解析,因此不是
多态的。
而静态方法是与类关联,而并非单个对象所关联。
希望大家能学习到知识,谢谢。