您的位置:首页 > 编程语言 > Java开发

java炒冷饭系列05 使用多态时需要注意的几点

2017-06-19 09:31 411 查看

缺陷:“覆盖”私有方法

我们试图像下面这样做也是无可厚非的:

public class PrivateOverride {
private void f(){
System.out.println("private.f()");
}

public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
}
}

class Derived extends PrivateOverride{
public void f(){
System.out.println("public.f()");
}
}


输出

PrivateOverride.f()

我们所期望的输出是public.f(),但是由于private方法被自动认为是final方法,而且对导出类是屏蔽的。因此,在这种情况下,Derived类中的f()方法就是一个全新的方法;

既然基类中的f()方法在子类Derived中不可见,因此甚至也不被重载。

结论就是:只有非private方法才可以被覆盖;但是还需要密切注意覆盖private方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的来执行。确切地说,在导出类中,对于基类中的private方法,最好采用不同的名字。

缺陷:域与静态方法

一旦你了解了多态机制,可能就会开始认为所有事物都可以多态地发生。然而,只有普通的方法调用可以是多态的。例如,如果你直接访问某个域,这个访问将在编译期进行解析,就像下面的示例所演示的

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();
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

当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。在本例中,为Super.fieldSub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域:它自己的和它从Super处得到的。然而,在引用Sub中的field时所产生的默认域并非Super版本的field域。因此,为了得到Super.field,必须显式地指明super.field

尽管这看起来好像会成为一个容易令人混淆的问题,但是在实践中,它实际上从来不会发生。首先,你通常会将所有的域都设置成private,因此不能直接访问它们,其副作用是只能调用方法来访问。另外,你可能不会对基类中的域和导出类中的域赋予相同的名字,因为这种做法容易令人混淆。

如果某个方法是静态的,它的行为就不具有多态性

class StaticSuper{
public static String staticGet(){
return "Base staticGet()";
}

public String dynamicGet(){
return "Base dynamicGet()";
}
}

class StaticSub extends StaticSuper {
public static String staticGet(){
return "Derived staticGet()";
}

public String dynamicGet(){
return "Derived dynamicGet()";
}

}
public class StaticPolymorphism {
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet());
System.out.println(sup.dynamicGet());
}
}


静态方法是与类,而并非与单个的对象相关联的。

总结

翻了两天书,才找到确切的依据,不容易啊

只有普通的方法调用可以是多态的

参考文献

《Java编程思想》8.2转机
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: