1. 对象的创建由什么完成
- 实际通过调用该类的有参或无参构造方法创建对象,但对象的创建并不由构造器完成.实际上通过new关键字调用构造方法时,系统在执行构造方法前会为该对象分配内存空间,并为这个对象执行默认初始化,此时该对象已经创建完成,然后通过构造器将该对象返回.
- 构造器无需指定返回类型,但并不是没有返回类型,实际返回的当前对象类型,如果没有返回类型则完全可以使用void返回关键字.
2. 构造方法什么时候会调用
public class Person{
private String name;
private int age;
public Person(String name){
this(name,0);/**!!!**/
System.out.println(name);
}
public Person(String name,int age){
System.out.println(name+""+age);
}
}
- 创建对象时
Person person = new Person("nan");
- 在构造方法中调用另外一个构造方法
如上 this(name,0);
该调用必须位于构造方法内,并且必须位于首行且只能调用一次。 如果没有指定的话构造方法默认首行为super(),去调用父类的无参构造方法,如果指定了this(),或者super,则系统不会添加。
3. 子类与父类
子类中拥有父类的变量和方法,包括静态成员和静态方法
- 静态成员变量和父类中的相同时:子类覆盖父类,则相当于各自分别有个变量
- 成员变量和父类中的相同时:子类覆盖父类,如果要在子类中访问父类中的该变量时则需使用super关键字
- 成员方法和父类中成员方法名和参数列表相同时:此时为重写,如果要在子类中访问父类的该方法时可使用super关键字
- 子类构造器中调用父类的构造器时使用super(...)调用,而且必须放首行,且只能调用一次.
注意
子类不能继承和重写父类的构造方法,而是采用隐式调用父类的构造方法 ,即如果子类没有显示调用父类的构造方法,系统会自动加入super()方法,该方法会去调用父类的无参构造方法,如果父类没有指定无参构造方法(系统自动添加,手动添加均可),则编译错误.如果显示调用父类构造方法,则系统不会隐式调用。
4. 子类继承父类引起的问题
破坏了父类的封装性,造成子类和父类的严重耦合. //子类可以直接访问父类的成员以及方法并重写
为了避免这些问题在设计父类时应尽量遵从以下原则:
- 父类成员尽可能使用private修饰
- 不要让子类随意重写父类的方法 父类中的方法用final修饰时子类则无法重写父类方法.
- 尽可能不在父类中调用可能被子类重写的方法. // 因为子类重写的方法有可能调用了自己类的一些成员,系统在初始化对象时先初始化父类,从而导致空指针异常
class Base{
public Base(){
test();
}
public void test(){
System.out.println("父类中的test方法");
}
}
class Sub extends Base{
private String name;
public void test(){
System.out.println("Sub name length:"+name.length());
}
public static void main(String[]args){
Sub sub = new Sub();//会引起空指针异常,首先会执行父类的无参构造方法,并调用test()方法,由于实际对象为Sub,则根据多态会调用子类重写的test方法,又因为子类name变量还没有被初始化,从而引起空指针异常.
}
}