Java多态中的若干问题

来源:互联网 发布:sybase用户数据库别名 编辑:程序博客网 时间:2024/06/05 05:55

    • 私有方法复写
    • 字段与静态方法
    • 构造器与多态

私有方法”复写”

子类继承父类后,private修饰的方法对子类是不可见的,因此存在复写的可能。当子类中方法名与父类私有方法名相同时,容易造成混淆,应尽量避免此种情况。
Thinking in java中的相关例子
import static net.mindview.util.Print.*;
public class PrivateOverride {
private void f() { print("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride {
public void f() { print("public f()"); }
}

输出:
private f()

字段与静态方法

字段和静态方法不具有多态特性。
名称相同的public修饰的子类和父类中的字段分配的内存空间并不相同,因此在向上转型后无法访问子类字段。
静态方法与类绑定,不与对象绑定,而多态是依靠对象与方法的动态绑定(运行时绑定)实现的,因此静态方法也不具有多态性。
Thinking in Java中的相关例子
class Super {
public int field = 0;
public int getField() { return field; }
}
class Sub extends Super {
public int field = 1;
public int getField() { return field; }
public int getSuperField() { return super.field; }
}
public class FieldAccess {
public static void main(String[] args) {
Super sup = new Sub(); // Upcast
System.out.println("sup.field = " + sup.field +
", sup.getField() = " + sup.getField());
Sub sub = new Sub();
System.out.println("sub.field = " +
sub.field + ", sub.getField() = " +
sub.getField() +
", sub.getSuperField() = " +
sub.getSuperField());
}
}

输出:
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0

构造器与多态

父类构造器会先于子类构造器调用
如果需要显式回收内存,内存回收函数顺序与构造器的调用调用顺序相反
构造器中的多态表现与内存中变量初始化顺序直接相关,初始化顺序如下:
1)对象分配空间受限全部初始化为0
2)调用父类构造器
3)子类的成员变量根据声明的先后顺序进行初始化
4)调用子类构造器
Thinking in Java中的相关例子
import static net.mindview.util.Print.*;
class Glyph {
void draw() { print("Glyph.draw()"); }
Glyph() {
print("Glyph() before draw()");
draw();
print("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
print("RoundGlyph.RoundGlyph(), radius = " + radius);
}
void draw() {
print("RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}

输出:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5

0 0