我们知道,Java程序是由一个个的类组成的。但程序在运行的时候,并非一开始就把所有的组成类都加载到内存中,而是在第一次使用某个类时才去加载它。某个类的字节码在被加载之前,只会安静的躺在硬盘的某个地方。
那么,怎么才算是“第一次使用”呢?像下面的声明算不算?
Apple a;
答案是No。Java规定第一次使用是指第一次调用类的static成员,这当然包括变量和方法。需要特别注意的是,构造方法也是static方法,只不过没有用static显式声明罢了。所以才会有“new一个对象的时候发生类的加载”这种说法,其实它只说对了一半,真正的原因是,new一个对象的时候调用了静态的构造方法。
加载的细节本文不再深究,就说加载过程中,类的哪些代码得到了执行。首先,类的static变量被初始化;然后是static块内的代码会被执行。
Java中的变量初始化其实分为三种:自动初始化;指定初始化;构造方法初始化。
自动初始化是指给变量分配了空间之后,要对这一块空间进行清零操作,因为这块空间还保留着以前的数据,而这些数据不是我们想要的,所以必须先将其清零。所谓清零,其实就是赋默认值,比如布尔类型设为false,int类型设为0,引用类型设为null等等。
指定初始化是指在声明变量的同时为其赋值,比如:
int a = 4;
这行代码的实际执行过程是这样的:先为a分配空间,接着清零,然后再赋值1。也就是说,无论怎样,自动初始化这个过程都是必不可少的,JVM会自动执行这个过程。
构造方法的初始化不必多说了,就是在构造函数内部为变量赋值。
可以看出,自动初始化是为了保证每个变量在使用之前都是干净的,即不会受到之前遗留数据的影响;而指定初始化则是为了用自定义的值代替默认值,另外对非static变量,指定初始化还可以使每个对象的该变量拥有同样的值(这样的坏处是不够灵活);构造方法初始化比指定初始化更加灵活,因为每个对象的状态可能是不同的,所有每个变量的值可能不同,而这只能在构造方法中完成。
对于static变量,只有前两种初始化,没有构造方法的初始化。构造方法是针对具体对象的。但是有人会问,难道在构造方法中不能访问static变量并为其赋值吗?这难道不是初始化?当然在构造方法中可以为static变量赋值,但是这已经不叫初始化了,第一次赋值才叫初始化。显然在调用构造方法之前,static变量已经赋过值了。
另外,变量的初始化还会涉及继承,这方面的东西以后再说。
那么,怎么才算是“第一次使用”呢?像下面的声明算不算?
Apple a;
答案是No。Java规定第一次使用是指第一次调用类的static成员,这当然包括变量和方法。需要特别注意的是,构造方法也是static方法,只不过没有用static显式声明罢了。所以才会有“new一个对象的时候发生类的加载”这种说法,其实它只说对了一半,真正的原因是,new一个对象的时候调用了静态的构造方法。
加载的细节本文不再深究,就说加载过程中,类的哪些代码得到了执行。首先,类的static变量被初始化;然后是static块内的代码会被执行。
Java中的变量初始化其实分为三种:自动初始化;指定初始化;构造方法初始化。
自动初始化是指给变量分配了空间之后,要对这一块空间进行清零操作,因为这块空间还保留着以前的数据,而这些数据不是我们想要的,所以必须先将其清零。所谓清零,其实就是赋默认值,比如布尔类型设为false,int类型设为0,引用类型设为null等等。
指定初始化是指在声明变量的同时为其赋值,比如:
int a = 4;
这行代码的实际执行过程是这样的:先为a分配空间,接着清零,然后再赋值1。也就是说,无论怎样,自动初始化这个过程都是必不可少的,JVM会自动执行这个过程。
构造方法的初始化不必多说了,就是在构造函数内部为变量赋值。
然后就是对象的初始化。new一个对象的时候,先在堆上为其分配空间,主要是为类中定义的非static变量分配空间,然后这些变量经历了和static变量一样的初始化过程:先自动初始化,然后若有指定初始化就执行。最后,才执行构造方法中的代码,对其赋值。
类加载的时候,并不发生非static变量的初始化,只初始化static变量;同样的,创建对象的时候,只为非static变量在堆上分配空间并初始化。
可以看出,自动初始化是为了保证每个变量在使用之前都是干净的,即不会受到之前遗留数据的影响;而指定初始化则是为了用自定义的值代替默认值,另外对非static变量,指定初始化还可以使每个对象的该变量拥有同样的值(这样的坏处是不够灵活);构造方法初始化比指定初始化更加灵活,因为每个对象的状态可能是不同的,所有每个变量的值可能不同,而这只能在构造方法中完成。
对于static变量,只有前两种初始化,没有构造方法的初始化。构造方法是针对具体对象的。但是有人会问,难道在构造方法中不能访问static变量并为其赋值吗?这难道不是初始化?当然在构造方法中可以为static变量赋值,但是这已经不叫初始化了,第一次赋值才叫初始化。显然在调用构造方法之前,static变量已经赋过值了。
另外,变量的初始化还会涉及继承,这方面的东西以后再说。