Java实现多态的机制是后期绑定。
但Java也有些地方可以用前期绑定,比如:final,static,private(隐式final)和构造方法(隐式static)是前期绑定。
另外,Java只有普通方法的调用可以是多态的,如果直接访问某个域,这个访问将在编译期进行解析。
举例
//子类
public class Son extends Battle {
public int a = 2;
public int getA(){
return a;
}
}
//父类
public class Battle {
public int a = 1;
public int getA(){
return a;
}
public static void main(String[] args) throws Exception {
Battle b = new Son();
System.out.println(b.a);
System.out.println(b.getA());
}
}
输出
构造器调用顺序
先看如下代码
class Meal {
Meal() { System.out.println("Meal()"); }
}
class Bread {
Bread() { System.out.println("Bread()"); }
}
class Cheese {
Cheese() { System.out.println("Cheese()"); }
}
class Lettuce {
Lettuce() { System.out.println("Lettuce()"); }
}
class Lunch extends Meal {
Lunch() { System.out.println("Lunch()"); }
}
class PortableLunch extends Lunch {
PortableLunch() { System.out.println("PortableLunch()"); }
}
public class Test extends PortableLunch {
private Bread b = new Bread();
private Cheese c = new Cheese();
private Lettuce l = new Lettuce();
public Test() { System.out.println("Test()"); }
public static void main(String[] args) {
new Test();
}
}
输出
执行步骤是:
1、调用父类构造器。这个步骤会不断递归下去,直到构造这种层次结构的根,然后是下一层的子类,直到最底层的子类。
1、按声明顺序调用成员的初始化方法。
3、调用子类构造器的主体。
同时调用层次中某一类的构造方法时,会先初始化成员变量。
按如下顺序初始化类中的东西:
1、静态属性初始化
2、静态方法块初始化
3、普通属性初始化
4、普通方法块初始化
5、构造函数初始化
构造器内部的多态
先看代码
class Glyph{
void draw(){
System.out.println("Glyph draw()");
}
Glyph(){
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after fraw()");
}
}
class RoundGlyph extends Glyph{
private int radius = 1;
RoundGlyph(int r){
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
}
void draw(){
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class Test {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
输出
分析一下代码运行过程:
- 在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的零。
- 如上文一般,虚拟机在查看类的类型信息的时候,如果发现有父类,则继续去加载父类的类文件,如果没有父类了,则开始初始化类,再然后执行构造器。
- 这时在执行Glyph的构造器时发现它调用了子类重写的draw方法,在这是一个多态。由于子类还没有初始化,这时radius是刚开始分配存储空间时初始化的0,因此打印出 RoundGlyph.draw(), radius = 0。
- 按照声明的顺序调用成员的初始化方法。
- 调用子类的构造器。