Java构造器使用方法及注意事项
Java构造器使用方法及注意事项
超类的构造器在子类的构造器运行之前运行,也就是说,在创建对象时,先运行超类中的构造器,然后再运行子类中的构造器,此时,如果在执行超类构造器的时候,构造器执行了可覆盖的方法,那么就会去调用子类中的该方法,而此时子类还未被实例化,此时就有可能出问题。
以一个例子说明:
publicclassSuper{ intage=10; protectedvoidsay(){ System.out.println("super"); } publicSuper(){ override(); } publicvoidoverride(){ System.out.println("superoverride"); } } classSubextendsSuper{ intage=9; privatefinalDatedate; publicSub(){ date=newDate(); } @Override publicvoidoverride(){ System.out.println(date); } @Override protectedvoidsay(){ System.out.println("sub"); } publicstaticvoidmain(String[]args){ Supersub=newSub(); sub.override(); //sub.say(); //System.out.println(sub.age); } }
创建两个类,一个Super.java,其中定义一个成员变量age=10,并且在构造器中调用了override()方法。Sub.java继承了Super.java,并且在构造方法中初始化了date。
现在我们执行main方法,控制台会打印出什么呢?是一个date?还是两个date?答案是先打印出null,然后打印出具体的date值。并且如果在Sub.java的override方法中调用date的任意方法时,会出现NPE
为什么会这样呢?
我们知道在使用new来创建对象的时候,会先检查该类是否继承自父类,如果是,则会先调用父类的构造方法,该案例中,在newSub()时,发现Sub是Super的子类,于是先调用Super的构造方法,在Super构造方法中,发现调用了override方法,于是又去寻找子类Sub是否重写了override方法,发现该子类重写了,则调用子类的override,打印出date,而此时date还未被初始化,所以值为null。
在父类的构造方法执行完毕后,再执行子类的构造方法,此时date被初始化了,所以再次调用override方法时,则会正确打印出date。
当调用sub.age,会打印出什么呢?是10还是9?
其实是打印出10,创建对象的时候,实例变量有两种类型,前面是声明类型,后面是实际类型
Supersub=newSub();
sub的声明类型为Super,实际类型为Sub。
当调用成员变量的时候,会先在声明类型中寻找该变量,如果该变量存在,则使用声明类型中的变量值,如果不存在,则在实际类型中去寻找该变量。
而调用方法的话,优先在子类中寻找对应方法,如果子类中不存在,再调用父类中方法。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持,如有疑问请留言,本站还有很多java的文章,欢迎大家搜索参阅!