TIJ上的一个例子:class Bowl {
Bowl(int er) {
System.out.println("Bowl(" + er + ")");
}
void f1(int er) {
System.out.println("f1(" + er + ")");
}
}class Table {
static Bowl bowl1 = new Bowl(1);
Table() {
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int er) {
System.out.println("f2(" + er + ")");
}
static Bowl bowl2 = new Bowl(2);
}class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
bowl4.f1(1);
}
void f3(int er) {
System.out.println("f3(" + er + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitialization { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1); }
static Table table = new Table();
static Cupboard cupboard = new Cupboard();} 运行结果如下:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(1)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(1)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(1)
f2(1)
f3(1)
同时,书上对这个例子进行了总结:
“总结一下对象的创建过程,假设有个名为Dog的类:
1.即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
2.然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3.当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4.这块存储空间将被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值,而引用则被设置成了null。
5.执行所有出现在字段定义处的初始化动作。
6.执行构造器。”
书上又说,“要执行main()(静态方法),必须加载StaticInitialization类,然后静态域table和cupboard被初始化,这将导致它们对应的类也被加载,并且由于它们也都包含静态的Bowl对象,因此Bowl随后也被加载。这样,在这个特殊的程序中的所有类在main()开始之前就都被加载了。”
不过我仍有疑问,加载StaticInitialization类后有关静态初始化的所有动作都会执行,那么有关静态初始化指的是什么?main()这个静态方法是否属于要静态初始化的一部分?网上有人(原文链接http://student.csdn.net/space.php?uid=120826&do=blog&id=13762)说“但主类比较特殊,主方法会在构造器之前,static变量初始化之后调用,这是由于Java的惰性初始化,在main方法被调用之前无法知道是否存在主类的实例。”不知大家怎么看。
另外,如果将static Table table = new Table();static Cupboard cupboard = new Cupboard();这两句放在main中,会出错“Illegal modifier for parameter table; only final is permitted”,这又是为什么?是static不能应用于局部变量只能作用于域的原因还是main的某些原因呢?
最后域的概念究竟如何理解?只是一个决定其中变量名的可见性和生命周期的概念吗?static的域又是一个怎样的概念?
问题挺多还挺杂,大家费心了。
Bowl(int er) {
System.out.println("Bowl(" + er + ")");
}
void f1(int er) {
System.out.println("f1(" + er + ")");
}
}class Table {
static Bowl bowl1 = new Bowl(1);
Table() {
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int er) {
System.out.println("f2(" + er + ")");
}
static Bowl bowl2 = new Bowl(2);
}class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
bowl4.f1(1);
}
void f3(int er) {
System.out.println("f3(" + er + ")");
}
static Bowl bowl5 = new Bowl(5);
}
public class StaticInitialization { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1); }
static Table table = new Table();
static Cupboard cupboard = new Cupboard();} 运行结果如下:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(1)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(1)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(1)
f2(1)
f3(1)
同时,书上对这个例子进行了总结:
“总结一下对象的创建过程,假设有个名为Dog的类:
1.即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
2.然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3.当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4.这块存储空间将被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值,而引用则被设置成了null。
5.执行所有出现在字段定义处的初始化动作。
6.执行构造器。”
书上又说,“要执行main()(静态方法),必须加载StaticInitialization类,然后静态域table和cupboard被初始化,这将导致它们对应的类也被加载,并且由于它们也都包含静态的Bowl对象,因此Bowl随后也被加载。这样,在这个特殊的程序中的所有类在main()开始之前就都被加载了。”
不过我仍有疑问,加载StaticInitialization类后有关静态初始化的所有动作都会执行,那么有关静态初始化指的是什么?main()这个静态方法是否属于要静态初始化的一部分?网上有人(原文链接http://student.csdn.net/space.php?uid=120826&do=blog&id=13762)说“但主类比较特殊,主方法会在构造器之前,static变量初始化之后调用,这是由于Java的惰性初始化,在main方法被调用之前无法知道是否存在主类的实例。”不知大家怎么看。
另外,如果将static Table table = new Table();static Cupboard cupboard = new Cupboard();这两句放在main中,会出错“Illegal modifier for parameter table; only final is permitted”,这又是为什么?是static不能应用于局部变量只能作用于域的原因还是main的某些原因呢?
最后域的概念究竟如何理解?只是一个决定其中变量名的可见性和生命周期的概念吗?static的域又是一个怎样的概念?
问题挺多还挺杂,大家费心了。
那么什么时候加载.class文件呢,我理解是第一次调用该类的静态方法或静态变量时加载。main方法和其他静态方法我认为是相同的。
例子如下,输出结果和楼主的例子一样
class Bowl {
Bowl(int er) {
System.out.println("Bowl(" + er + ")");
}
void f1(int er) {
System.out.println("f1(" + er + ")");
}
}class Table {
static Bowl bowl1 = new Bowl(1);
Table() {
System.out.println("Table()");
bowl2.f1(1);
}
void f2(int er) {
System.out.println("f2(" + er + ")");
}
static Bowl bowl2 = new Bowl(2);
}class Cupboard {
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
bowl4.f1(1);
}
void f3(int er) {
System.out.println("f3(" + er + ")");
}
static Bowl bowl5 = new Bowl(5);
}
class StaticInitialization { /**
* @param args
*/
public static void a() {
// TODO Auto-generated method stub
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1); }
static Table table = new Table();
static Cupboard cupboard = new Cupboard();}public class Test
{
public static void main(String[] args)
{
StaticInitialization.a();
}
}
关于这点, 是因为在java的变量中, 只有域变量才能被定义为static的, 静态域也叫类域, 从这个方面来看, 局部变量是不能定义为static的. 静态域是属于类的, 而不属于某个对象, 它是一个公共的资源.
另外, 对于域, 我个人觉得, 域就是指的类的属性, 里面的所有的变量, 因为所谓的域初始化, 都是指的是实例化这个类时对变量的初始化. 以上都只是个人理解, 有什么不对的地方, 请指出, 谢谢.
是啊,我也感觉 field 应译为“字段”,或者意译为“成员变量”。“域”的话感觉挺不知所云的,呵呵。
class Foo {
int bar;
}bar就是Foo类的一个域,即一个成员变量!域、字段、成员变量,指的都是一个东西,不同叫法而已。但是“域”有时还指“作用域”(Scope),那就完全是另一种东西了。建议楼主看英文原著!