继承
- 每个类有且只有一个父类,没有声明父类的,其父类为Object,子类继承了父类的非Private方法和变量,final类不能被继承。
- new过程中,父类先进行初始化,可通过super调用父类相应的构造方法,没有super的情况下 ,调用父类的默认构造方法(没有默认构造方法则报错)。
- 子类变量和方法与父类重名的情况下,可通过super访问父类的变量和方法。
- 父类和子类重名的private变量和方法,那么在子类中访问的是子类的,父类中访问的是父类的,没有任何关系;如果是public的变量和方法,在类内访问是当前类的,类外访问要看这个类的静态类型是子类还是父类,如果是子类,就访问子类的。
- 继承有可能会破坏封装,例如子类在扩展父类时,如果不知道父类的实现细节,则有可能写出错误的代码;而父类的实现细节也不能随意修改,否则可能影响子类;父类不能随意增加公开方法,因为这样所有子类也添加了,而子类有可能要重写该方法才能保证方法的正确性。
- 避免继承的方法有:使用final关键字,使用组合代替继承(父类修改为成员变量),使用接口。
- 父类型转换为子类型的时候需要使用instanceof判断动态类型,否则可能报运行时错误。
静态绑定与动态绑定
- 程序编译时决定的称为静态绑定,实例变量,静态变量,静态方法,private方法都是静态绑定。
- Java中方法默认是虚函数,C++则需要使用关键字virtual才能声明虚函数。
- 子类对象可以赋值给父类引用变量,这叫多态,实际执行的是子类方法,这叫动态绑定。
重载与重写
- 重载是指方法名称相同但参数签名不同的方法,例如参数个数,类型,顺序。
- 重写是指子类重写与父类相同参数签名的方法,当有多个重名函数时,决定调用哪个函数的过程中,首先是按照参数类型进行匹配的,参数类型都一样则看变量的动态类型,进行动态绑定,
private或final方法不能被重写。 - 重写时的@Override不是必须的,该注解的作用是提高代码可读性以及有助于编译器检查错误。
- 子类重写父类方法时不能降低父类方法的可见性,但是可以提高父类方法的可见性。
接口
- 接口可以定义变量,修饰符可以不写,默认是public static final。
- 接口可以继承,与类不同的是,接口可以有多个父接口。
- 从Java8起,接口可以有静态方法。
- 从Java8起,接口可以有默认方法(default),实现类可以改变它的实现,也可以不改变。
抽象类
- 如何理解抽象类:狗是具体对象,动物则是抽象概念,樱桃是具体对象,水果则是抽象概念。
- 抽象类和抽象方法使用abstract这个关键字来声明,抽象方法类似于C++里的纯虚函数,抽象类不能创建具体的对象,一个类继承抽象类后必须实现所有抽象方法。
- 抽象类和接口是配合而非替代关系,它们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。
内部类
- 内部类通常与它的外部类有比较密切的关系,而与其它类关系不大,定义在类内部,可以实现对外部完全隐藏,有更好的封装性,每个内部类最终都会被编译为一个独立的类。
- 内部类可以方便地访问外部类的私有变量,内部类有四种,静态内部类,成员内部类,方法内部类,匿名内部类。
- 静态内部类通过关键字static实现,它可以访问外部类的所有静态变量和方法,但是不能访问实例变量和方法。
- 如果一个类与外部类关系密切,且不依赖于外部类实例,则可以考虑定义为静态内部类,如Integer类内部有个私有静态内部类IntegerCache用于支持整数的自动装箱。
- 成员内部类相对于静态内部类而言,少了static关键字,成员内部类总是与一个外部类对象相连,成员内部类不能定义静态变量和方法,final变量除外。
- 定义在方法里的类为方法内部类,如果是静态方法,那么它只能访问外部类的静态变量和方法,方法内部类类似于成员内部类。
- 匿名内部类通过创建一个接口或者类来定义,创建对象的同时定义类,很多回调接口的创建都是匿名内部类,其它部分与方法内部类类似。