class Animal{
String color="red";
Animal(){
print();
color="black";
}
void print(){
System.out.println("animal color is "+color);
}
}class Cat extends Animal{
String color="yellow";
Cat(){
print();
super.print();
}
void print(){
System.out.println("cat color is "+color);
}
public static void main(String[] args){
new Cat();
}
}结果是:
cat color is null
cat color is yellow
animal color is black
疑问:
1.当子类构造函数去调用父类构造函数时,如果父类构造函数中调用的成员函数被子类覆盖过,那么就用子类?
2.为什么是null? 显示初始化不是优先于构造函数么?当构造函数启动时,成员变量不是已经被显示初始化了么?
String color="red";
Animal(){
print();
color="black";
}
void print(){
System.out.println("animal color is "+color);
}
}class Cat extends Animal{
String color="yellow";
Cat(){
print();
super.print();
}
void print(){
System.out.println("cat color is "+color);
}
public static void main(String[] args){
new Cat();
}
}结果是:
cat color is null
cat color is yellow
animal color is black
疑问:
1.当子类构造函数去调用父类构造函数时,如果父类构造函数中调用的成员函数被子类覆盖过,那么就用子类?
2.为什么是null? 显示初始化不是优先于构造函数么?当构造函数启动时,成员变量不是已经被显示初始化了么?
2.new Cat() 先调用父类构造方法 调print()方法 所以null
2.之所以是null是因为当父类调用子类的print方法时,子类的color变量还没有执行初始化。显示初始化时先于构造函数没错,但是指的是当前的类的变量的初始化,楼主给出的例子中,JVM首先初始化了父类的color变量,然后调用了子类的print方法,但是此时还没有初始化子类的color变量。而子类的方法调用的是子类的color变量,所以打印出来的就是null了。当构造函数启动时,成员变量是被加载,而不是初始化,也就是说这个指针存在,但是这个指针不指向任何对象。
class A {
{System.out.println("执行顺序1");} //这里叫做初始化处理块
public A() {
System.out.println("执行顺序2");
}
}class B extends A {
{System.out.println("执行顺序3");} //初始化处理块,String color = "yellow"; 相当于
//String color; //声明变量,相当于给变量分配内存空间并初始化为缺省值
//{color = "yellow"} //在初始化块给变量赋值
//所以,从执行顺序来看,LZ应该知道为什么是null了吧
public B() {
System.out.println("执行顺序4");
}
}public class C {
public static void main(Srting[] args) {
new B();
}
}
new 子类()的执行顺序是
1 父类初始化块
2 父类构造方法
3 子类初始化块
4 子类构造方法LZ再好好体会一下吧
2.为什么会是null?这个很明显,对象是先初始化然后复制,虽然String color在构造函数之前,但是他的复制却是要等待对象初始化完成之后。而对象创建是构造函数执行完成之后,所以你在构造函数中调用color属性,而这个时候color是还没有赋值的。那么String的初始默认为null。所以也就打印null咯
有点小疑问:既然赋值在初始化之后,可以解释子类构造函数中super()那句的打印结果,但为什么下一行print()打印的结果有值。
能否这样理解,当jvm执行到子类构造函数的super()之前,已经做好了什么事?真是太痛苦了遇到”先有鸡还是先有蛋“这样的问题。我想这是大家公认的结果吧:先初始化父类的静态代码--->初始化子类的静态代码-->初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数
也就是说当到了子类构造函数时,前面的事都完了。。 又回到这个问题的起点,我崩溃了- -!!
static{
System.out.println("Static Animal....");
}
{
System.out.println("Animal....");
}
public String color="red";
Animal(){
print();
color="black";
}
void print(){
System.out.println("animal color is "+color);
}
}public class Cat extends Animal{
static{
System.out.println("Static Cat.....");
}
{
System.out.println("Cat...");
}
public String color="yellow";
Cat(){
print();
super.print();
}
void print(){
System.out.println("cat color is "+color);
}
public static void main(String[] args){
new Cat();
}
}