1.父类中的private方法是不能被子类覆盖的,即隐藏了final关键字。如果子类中有和父类同名的方法,且父类的方法是private,那这两个方法只是名字相同,并没有任何关系。
2.面向对象的三个特征:封装,继承,多态。
3.Java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定(即动态绑定)。
JAVA中所有方法都是通过动态绑定实现多态。
4.只有普通的方法调用可以是多态的,如果直接访问某个域,这个访问在编译期进行解析。
即Base base=new Sub(); base.field的值是Base类中的field的值(假定是public的)。
如何避免这种尴尬:
把域设置为private,只提供get/set方法。
5.静态方法不具备多态性。因为静态方法是与类,而并非与单个的对象相关联的。
6.如果在一个构造器的内部调用正在构造的对象的某个动态绑定方法,那调用的就是子类的那个方法,这将招致灾难。
因为此时子类的成员尚未被初始化,如果在那个方法中用到了成员,那基本类型会有默认值(如int型是0),而对象类型是null,所以可能会引发空指针错误。
如代码
class Demo { public void haha(){ System.out.println("haha"); } } class Base { public Base() { this.tt(); } void tt() { } } class Sub extends Base { private Demo demo=new Demo(); public Sub(){} void tt() { demo.haha(); } } public class A { public static void main(String args[]) { Sub base=new Sub(); base.tt(); } }会报错:
Exception in thread "main" java.lang.NullPointerException
at test.Sub.tt(A.java:18)at test.Base.<init>(A.java:9)at test.Sub.<init>(A.java:16)at test.A.main(A.java:23)那如何避免这种情况呢?记住编写构造函数的一条有效的准则:
用尽可能简单的方法使对象进入正常状态,如果可以的话,避免调用其他方法。在构造器内唯一能安全调用的方法是基类的final方法(和private方法)。
7.协变返回类型
在子类重写父类的方法时,可以修改返回类型。 比如父类的方法return Base类的对象,那子类的方法中可以return Sub类的对象。
8.在不知道该用继承还是组合时,首选组合。因为组合更灵活,它可以动态选择类型,相反,继承在编译时就需要知道确定类型。使用组合可以在运行时改变引用的类型,但我们不能再运行期间决定继承不同的对象,因为它要求在编译期间完全确定下来。
9.向下转型与运行时类型识别
比如 (Sub)base,把声明为父类对象的引用转换为子类对象的引用,会在运行时进行类型检查,这种在运行期间对类型进行检查的行为称作运行时类型识别(RTTI)。