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.field和Sub.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转机相关文章推荐
- Windows+eclipse+Android+java+api+opencv使用需要注意的几点
- Java使用HashMap进行遍历时候需要注意的几点
- java反射reflection需要注意的几点
- 旧的代码在2005下使用需要注意以下几点
- 使用NOSQL的MongoDB建立索引时需要注意的几点建议和Explain优化分析
- 关于mysql索引使用需要注意的几点
- ATL/WTL使用的几点需要注意的地方
- 使用Java中的final变量需要注意的地方。
- 使用php apc模块需要注意的几点
- 实现java.lang.Object.equals(Object)需要注意哪几点?
- 使用Java中的final变量需要注意的地方
- 使用NOSQL的MongoDB建立索引时需要注意的几点建议和Explain优化分析
- 使用switch语句需要注意的几点
- 使用Java中的final变量需要注意的地方
- Java异常处理需要注意的几点
- 使用Java中的final变量需要注意的地方。
- 使用innerHTML时需要注意的几点问题
- 使用SqlDataAdapter时,需要注意的几点
- 在java中使用常量变量的一些需要注意的地方
- 爱上MVC3系列~使用@需要注意的地方