1.类变量初始化:  

class Price{
	final static Price INSTANCE = new Price(2.8);
	static double initPrice = 20;	
	double currentPrice ;
	public Price (double discount) {
		currentPrice = initPrice - discount;	
	}
}
public class PriceTest{
	public static void main(String[] args){
		System.out.println(Price.INSTANCE.currentPrice);
		Price price = new Price(2.8);
		System.out.println(price.currentPrice);
	}	
}

 

  (1)系统先为INSTANCE ,initPrice两个类变量分配内存空间,此时INSTANCE和initPrice分别为null和0;

(2)系统为INSTANCE,initPrice两个变量赋值,对INSTANCE赋值时调用Price(2.8),创建Price实例,此时initPrice还为0,所以INSTANTCE的currentPrice为-2.8。接着系统为initPrice赋值为20,但是对INSTANCE中的currentPrice没影响了,所以打印的结果为-2.8;

注意:如果将1、2处的代码交换位置,则不会出现这个问题了。

2.父类调用子类对象的实例变量

/**
 * 1.在this在构造器中,this代表正在初始化的java对象,[此时this位于Base()构造器内,
 *    但这些代码实际放在Derived()构造器内执行--是Derive()构造器 隐式调用了Base()构
 *    造器代码],即new的这个Derived对象,因此(2)处输出"Derived";
 *  2.因为this虽然代表Derived对象,但它位于Base构造器中,它的编译时类型是Base,而
 *     它实际上引用了一个Derived对象。编译时类型和运行时类型不同时,通过该变量访问
 *     它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定。但通过该变量
 *     调用它引用的对象实例方法时,该方法行为将由它实际所引用对象来决定。
 *  
 */
class Base{
	private int i = 2;
	public Base(){
		System.out.println(this.i);//(1)		                                       
		display();
		System.out.println(this.getClass().getName());//(2)
	}
	public void display(){
		System.out.println("super:"+i);//(3)
	}
}
class Derived extends Base{
	private int i =22;
	public Derived(){
		i = 222;
	}
	public void display(){
		System.out.println("self:"+i);//(4)
	}
}
public class Test{
	public static void main(String[] args){
		new Derived();//(5)
	}
}

 

 注意:构造器只负责将java对象实例变量执行初始化(即赋初值),在执行构造器代码之前,改对象的内存已经分配好了,这些内存里值要么是null要么是0或者false。

3.

/**
 * 如果父类构造器调用了被子类重写的方法,且通过子类构造器来创建子类对象
 * 调用(不管显示、隐式)了这个父类构造器,就会导致子类的重写方法在子类构
 * 造器的所有代码之前被执行,从而导致子类的重写方法访问不到子类的实例变量
 * 值的情形。
 */
class Animal{
	private String desc;
	public Animal(){
		this.desc = getDesc( );
	}
	public String getDesc(){
		return "Animal";
	}
	public String toString(){
		return desc;
	}
}
public class Wolf extends Animal{
	private String name;
	private double weight;
	public Wolf(String name,double weight){
		this.name = name;
		this.weight = weight;
	}
	@Override
	public String getDesc(){
		return "Wolf[name="+name+",weight="+weight+"]";
	}
	public static void main(String[] args){
		System.out.println(new Wolf("红太狼",120));//Wolf[name=null,weight=0.0]
	}
}