class Price
{
// 类成员是Price实例
final static Price INSTANCE = new Price(2.8);
// 在定义一个类变量。
static double initPrice = 20;
// 定义该Price的currentPrice实例变量
double currentPrice;
public Price(double discount)
{
// 根据静态变量计算实例变量
currentPrice = initPrice - discount;
}
}
public class PriceTest
{
public static void main(String[] args)
{
// 通过Price的INSTANCE访问currentPrice实例变量
System.out.println(Price.INSTANCE.currentPrice); // ①
// 显式创建Price实例
Price p = new Price(2.8);
// 通过先是创建的Price实例访问currentPrice实例变量
System.out.println(p.currentPrice); // ②
}
}
最终输出多少呢
没想到吧
我们可以从字节码上可以查看到这个问题
类加载进行准备阶段时final static Price INSTANCE 这个类变量 没有进行初始化赋值 ,此时是为null 以及 static double initPrice 为0 此时已经给2个类变量已经分配好空间 ,当进入到初始化阶段时 由于 代码执行从上往下执行 ,会优先 执行 new Price(2.8); 但是此时的 initPrice 这个类变量的初始化还没有被执行 所以为0 ,所以 会打印 -2.8
至于下面一个 代码执行 就是一个构造方法执行
我们对调一下2个类变量的顺序
class Price
{
// 在定义一个类变量。
static double initPrice = 20;
// 类成员是Price实例
final static Price INSTANCE = new Price(2.8);
// 定义该Price的currentPrice实例变量
double currentPrice;
public Price(double discount)
{
// 根据静态变量计算实例变量
currentPrice = initPrice - discount;
}
}
public class PriceTest
{
public static void main(String[] args)
{
// 通过Price的INSTANCE访问currentPrice实例变量
System.out.println(Price.INSTANCE.currentPrice); // ①
// 显式创建Price实例
Price p = new Price(2.8);
// 通过先是创建的Price实例访问currentPrice实例变量
System.out.println(p.currentPrice); // ②
}
}
类加载的准备阶段 已上面相同 ,初始化阶段 由于 代码执行从上往下执行 现在 由于2个类变量执行顺序发生改变 ,先执行了 initPrice 类变量的初始化 所以最终显示 17.2
还有一个东西 那就是 initPrice 也上 final
class Price
{
// 类成员是Price实例
final static Price INSTANCE = new Price(2.8);
// 在定义一个类变量。
final static double initPrice = 20;
// 定义该Price的currentPrice实例变量
double currentPrice;
public Price(double discount)
{
// 根据静态变量计算实例变量
currentPrice = initPrice - discount;
}
}
public class PriceTest
{
public static void main(String[] args)
{
// 通过Price的INSTANCE访问currentPrice实例变量
System.out.println(Price.INSTANCE.currentPrice); // ①
// 显式创建Price实例
Price p = new Price(2.8);
// 通过先是创建的Price实例访问currentPrice实例变量
System.out.println(p.currentPrice); // ②
}
}
这个原因是因为 final static double initPrice 这个类变量 他是编译阶段就知道的一个固定值 ,所以在类的准备阶段 给这个类变量赋值
然后进入到 初始化阶段 由于 代码执行从上往下执行 进行new Price(2.8) ,但是 initPrice这个类编已经赋值完成 所以最终为 17.2