Java变量可分为局部变量和成员变量,其中局部变量又可分为三类:形参、方法内局部变量、代码块局部变量。
类体内定义的变量称为成员变量(Field),没有使用static修饰的称为非静态变量或实例变量;如果使用static修饰就称为静态变量或类变量。
对于实例变量而言,该类每创建一次实例,就需要为实例变量分配一块内存空间。
实例变量初始化内存分配:
我们来看下面这段代码
public class Test {
String name;
int age;
public Test(String name ,int age){
System.out.println("构造器");
this.name = name;
//weight = 2.5;
this.age = age;
}
{
System.out.println("非静态构造器");
weight = 2.0;
}
public String toString(){
System.out.println(weight);
return "";
}
double weight = 2.3;
public static void main(String[] args) {
Test ti = new Test("x", 4);
ti.toString();
}
}
问题:这里输出结果是什么?weight是什么?
答:输出结果为:
"非静态构造器"
"构造器"
2.3
是不是有人觉得输出2.3很奇怪?
该代码执行顺序是这样的:
1.在栈内存中申请weight的空间,注意此时是默认值即0.0
2.执行非静态构造器,注意只分配空间不会赋值,因此对于这段代码来说没有任何意义。
3.执行构造函数赋值,赋值顺序按照指定初始值和非静态构造器顺序赋值,也就说在执行new Test()的时候才对weight赋值
先赋给2.0,再赋给2.3,最后执行构造器中的剩余的方法。(最终值为2.5而不是2.3)
因此也就是说:实例变量的初始化过程都是先在堆内存中申请空间,无论何时赋值,最先都是在调用构造器的时候才会对其赋值,赋值的顺序按照初始化值或非静态初始化块的顺序执行,最后执行构造函数中的赋值。
类变量初始化内存分配:
类变量初始化过程与实力变量类似,只不过由:申请空间-构造函数-赋值三步简化为:申请空间-赋值两部了。我们来看下面例子:
Class Price{
final static Price INSTANCE = new Price(2.8);
static double initPrice = 20;
double currentPrice;
public Price(double discount){
currentPrice = initPrice - discount;
}
}
main(){
system.out.println(Price.INSTANCE.currentPrice);
}
问题:这里输出结果是什么?
答:输出结果为:
-2.8
是不是有人觉得输出-2.8很奇怪?
该代码执行顺序是这样的:
1.在栈内存中申请INSTANCE和initPrice的空间;2.按照顺序赋值,先执行new Price();,此时initPrice的值为默认值即0。因此currentPrice = -2.8
3.initPrice赋值20