30、继承是面向对象的三大特征之一,也是实现软件复用的重要手段。java的继承具有单继承的特点,每个子类只有一个直接父类。
31、java.lang.Object类是所有类的父类,要么是其直接父类,要么是其间接父类。因此所有的java对象都可调用java.lang.Object类所定义的实例方法。从子类扩展了父类,但从父类的角度看,父类派生了子类,也就是说,扩展和派生所描述的是同一个动作,只是观察角度不用而已。
32、方法的重写要遵循两同两小一大规则,两同是方法名相同,形参列表相同,两小指的是子类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等,一大指的是子类方法的访问权限应比父类方法的访问权限更大或相等。尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。
33、如果需要在子类方法中调用父类中被覆盖的方法,则可以使用super或者父类类名作为调用者来调用父类中被覆盖的方法。如果父类方法具有private访问权限,则该方法对其子类是隐藏的,因此子类无法访问该方法,也就无法重写该方法。
34、父类方法和子类方法之间也可能发生重载,因为子类会获得父类方法,如果子类定义一个与父类方法有相同的方法名,但形参列表不同的方法,就会形成父类方法和子类方法的重载。
35、如果子类定义了和父类同名的实例变量,则会发生子类实例变量隐藏父类实例变量的情形,在正常情况下,子类定义的方法直接访问该实例变量会访问到子类中定义的实例变量,无法访问到父类中隐藏的实例变量。
36、如果在某个方法中访问名为a的成员变量,但没有显示指定调用者,则系统查找的顺序是①查找该方法中是否有名为a的局部变量。②查找当前类中是否包含名为a的成员变量。③查找a的直接父类是否包含为a的成员变量,依次上述到a的所有父类,直到java.lang.Object类,还是找不到就抛出异常。
37、为了在子类方法中访问父类中定义的、被隐藏的实例变量,或为了在子类方法中调用父类中定义、被覆盖的方法,可以通过super.作为限定来调用这些实例变量和实例方法。
38、在一个构造器中调用另一个构造器使用this调用来完成,在子类构造器中调用父类构造器使用super调用来完成。
39、不管是否使用super调用来执行父类构造器的初始化代码,子类构造器总会调用父类构造器一次。子类构造器调用父类构造器分如下几种情况。①子类构造器执行体的第一行使用super显示调用父类构造器,系统将根据super调用里传入实参列表调用父类对应的构造器。②子类构造器执行体的第一行代码使用this显示调用本类中重载的构造器,系统将根据this调用里传入的实参列表调用本类中另一个构造器。执行本类中另一个构造器的同时会调用父类构造器。③子类构造器执行体中既没有super调用,也没有this调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器。
40、java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。与方法不用的是,对象的实例变量则不具备多态性。
41、通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时类型定义的成员变量。
42、当进行强制类型转换时需要注意:①基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括整数型、字符型和浮点型。但数值类型和布尔类型之间不能进行类型转换。②引用类型之间的转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。
43、当把子类对象赋给父类引用变量时,被称为向上转型,这种转型总是可以成功的,这也从另一个侧面证实了子类是一种特殊的父类。这种转型只是表明这个引用变量的编译时类型是父类,但实际执行它的方法时,依然表现出子类对象的行为方式。但把一个父类对象赋给子类引用变量时,就需要进行强制类型转换,而且还可能在运行时产生ClssCastException异常,使用 instanceof运算符可以让强制类型转换更安全。
44、继承是实现类复用的重要手段,但继承带来了一个最大的坏处:破坏封装。相比之下,组合也是实现类复用的重要方式,而采用组合方式来实现类复用则能提供更好的封装性。
45、为了保证父类有良好的封装性,不会被子类随意修改,设计父类通常应该遵循如下规则:①尽量隐藏父类的内部数据。尽量把父类的所有成员变量都设置成private访问类型,不要让子类直接访问父类的成员变量。②不要让子类可以随意访问、修改父类的方法。父类中那些仅为辅助其他的工具方法,应该使用private访问控制符修饰,让子类无法访问该方法,如果父类中的方法需要被外部类调用,则必须以public访问控制符修饰,但又不希望子类重写该方法,可以使用final修饰符来修饰方法,如果希望父类的某个方法被子类重写,但不希望被其他类自由访问,则可以使用protected来修饰该方法。③尽量不要在父类构造器中调用将被子类重写的方法。
46、如果想把某些类设置成最终类,即不能被当成父类,则可以使用final修饰这个类。除此之外,使用private修饰这个类的所用构造器,从而保证子类无法调用该类的构造器,也就无法继承该类。对于把所有的构造器都是用private修饰的父类而言,可以另外提供一个静态方法,用于创建该类的实例。
47、什么时候需要从父类派生新的子类?①子类需要增加额外属性,而不仅仅是属性值的改变。②子类需要增加自己独有的行为方式。
48、初始化块的修饰符只能是static,使用static修饰的初始化块被称为静态初始化块。初始化块里的代码可以包含任何可执行语句,包括定义局部变量、调用其他对象的方法,以及使用分支、循环语句等。
49、初始化块虽然也是java类的一种成员,但是它没有名字,也就没有标识,因此无法通过类、对象来调用初始化块。初始化块只在创建java对象时隐式执行,而且在执行构造器之前执行。
50、当java创建一个对象时,系统现为该对象的所有实例变量分配内存,接着程序开始对这些实例变量执行初始化,其初始化顺序是:先执行初始化块或声明实例变量时指定的初始值,再执行构造器里指定的初始值。
51、静态初始化块是类相关的,系统将在类初试话阶段执行静态初始化块,而不是在创建对象的时候才执行。因此静态初始化块总是比普通初始化块先执行。静态初始化块是类相关的,用于对整个类进行初始化处理,通常用于对类变量执行初始化处理。静态初始化块不能对实例变量进行初始化处理。
52、静态初始化块也属于类的静态成员,同样需要遵循静态成员不能直接访问非静态成员的规则。因此静态初始化块不能访问非静态成员,包括实例变量和实例方法。
53、java系统加载并初始化某个类时,总是保证该类的所有父类全部加载并初始化。静态初始化块和声明静态成员变量时所指定的初始化值都是该类的初始化代码,它们的执行顺序与源程序中的排列顺序相同。