标题:求大牛们帮忙分析一下!
只看楼主
chengsencs
Rank: 1
等 级:新手上路
帖 子:109
专家分:0
注 册:2006-7-24
 问题点数:0 回复次数:21 
求大牛们帮忙分析一下!

今天看到的一个程序,很晕!!
class Cup
{
Cup(int marker)
{
System.out.println("Cup(" + marker + ")");
}
void f(int marker)
{
System.out.println("f(" + marker + ")");
}
}
class Cups
{
static Cup c1=new Cup(1);
Cup c3=new Cup(3);
static Cup c2= new Cup(2);
Cups()
{
System.out.println("Cups()");
}
Cup c4=new Cup(4);
}
public class E
{
Cups c=new Cups(); 1
{
System.out.println("Hello");
}
public static void main(String[] args)
{
System.out.println("Inside main()");
Cups.c1.f(99);
E x=new E();
}
static Cups x = new Cups();
}
运行结果:
D:\>javac E.java

D:\>java E
Cup(1)
Cup(2)
Cup(3)
Cup(4)
Cups()
Inside main()
f(99)
Cup(3)
Cup(4)
Cups()
Hello

为什么输出的顺序是这样的?
能不能详细的解释一下?
谢谢。

搜索更多相关主题的帖子: void 
2007-01-31 15:38
千里冰封
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:灌水之王
等 级:版主
威 望:155
帖 子:28477
专家分:59
注 册:2006-2-26
得分:0 
以下是引用chengsencs在2007-1-31 15:38:53的发言:

今天看到的一个程序,很晕!!
class Cup
{
Cup(int marker)
{
System.out.println("Cup(" + marker + ")");
}
void f(int marker)
{
System.out.println("f(" + marker + ")");
}
}
class Cups
{
static Cup c1=new Cup(1);
Cup c3=new Cup(3);
static Cup c2= new Cup(2);
Cups()
{
System.out.println("Cups()");
}
Cup c4=new Cup(4);
}
public class E
{
Cups c=new Cups(); 1
{
System.out.println("Hello");
}
public static void main(String[] args)
{
System.out.println("Inside main()");
Cups.c1.f(99);
E x=new E();
}
static Cups x = new Cups();
}
运行结果:
D:\>javac E.java

D:\>java E
Cup(1)
Cup(2)
Cup(3)
Cup(4)
Cups()
Inside main()
f(99)
Cup(3)
Cup(4)
Cups()
Hello

为什么输出的顺序是这样的?
能不能详细的解释一下?
谢谢。

这个题目是很基础的初始化顺序问题,你不要被这些输出吓到了,其实知道了初始化的顺序之后,你就会发现,这种题目一点也不难
初始化顺序如下:
父类静态成员变量,静态初始化块,子类静态成员变量,静态初始化块,父类成员变量,构造函数,子类成员变量,构造函数.

我们现在分析一下这个程序

这个程序的主类就是E类,那么,JVM在装载这个类的时候,必须先初始化这个类的静态成员变量,这个类只有一个静态成员变量,那就是static Cups x = new Cups();
不要以为它写在下面就会晚一点执行,它写哪都是第一个执行,当然,如果有多个静态成员变量的话,那么就是按出现的顺序执行的了,既然它首先执行,我们可以看到,它首先就得调用new Cups() 这个方法,这个时候JVM就要找Cups这个类了,同样,在初始化Cups之前,也要初始化它的静态成员变量,它有c1,c2 两个变量是静态的,所以首先执行的是new Cup(1),new Cup(2),这个时候,输出
Cup(1)
Cup(2)
然后它再初始化成员变量,成员变量也有两个,分别是c3,c4,这个时候输出
Cup(3)
Cup(4)
静态成员和成员变量都初始化好了以后,再调用构造函数,这个时候输出
Cups()

这个时候,static Cups x = new Cups();这个语句算是执行完了,开始进入main方法了,main方法第一句就是System.out.println("Inside main()");
所以这个时候输出
Inside main()
然后调用Cups.c1.f(99); 很显然,此时输出是
f(99)

然后再执行E x=new E();
前面已经说了,调用构造函数之前,必须把成员变量给初始化先,这个E类的成员变量是
Cups c=new Cups();
{
System.out.println("Hello");
}

第一个是一句语句,第二个是一个语句块,这两个是同等级别,所以按顺序执行,先执行Cups c=new Cups();
看到这句,我们就知道了,要构造出一个Cups的对象来,我们前面可以看到,这个时候Cups这个类已经被JVM装载进来了,所以它的static块就不会再执行了,因为静态初始化只在类刚刚装入JVM的时候执行的,
这个时候,在调用构造函数之前,还得先初始化成员变量,这个类的成员变量有两个,分别是c3,c4,所以它会分别调用new Cup(3),new Cup(4),所以此时的输出为:
Cup(3)
Cup(4)

这个时候,对象c的成员变量已经初始化好了,该调用它的构造函数了,所以输出为
Cups()
调用完这句后,Cups c=new Cups();这句就已经执行完了,下面就执行初始化块
{
System.out.println("Hello");
}
所以,最后输出为:
Hello


可惜不是你,陪我到最后
2007-01-31 16:02
angeloc
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:36
帖 子:1353
专家分:0
注 册:2006-11-21
得分:0 
首先从程序入口看
public static void main(String[] args)
{
System.out.println("Inside main()");
Cups.c1.f(99);
E x=new E();
}
程序是从入口点开始运行的,那么按常理应该显示"Inside main()".
但是static Cups x = new Cups(); 的存在,使得编译器在类public class E调用前首先
对类中STATIC的成员进行构造,同样class Cups调用前首先初始化static Cup c1=new Cup(1)
和static Cup c2= new Cup(2).
所以显示:Cup(1)
Cup(2)
然后 class Cups对成员Cup c3=new Cup(3),Cup c4=new Cup(4)初始化
显示: Cup(3)
Cup(4)
再调用class Cups本身的构造函数
显示: Cups()

这时候完成class Cups的全部初始化,回到main中调用System.out.println("Inside main()")
显示: Inside main()
之后再调用Cups.c1.f(99)
显示: f(99)
最后E x=new E()实例化class E,这时候class E的static成员已经在之前就初始化了,所以不再
调用,但还会初始化Cup c3=new Cup(3)和Cup c4=new Cup(4),并且执行默认构造函数,之后回到
class E调用构造函数显示"HELLO"

显示: Cup(3)
Cup(4)
Cups()
Hello



老牛明知夕阳晚,不用扬鞭自奋蹄; Angelo\'s BLOG
2007-01-31 16:24
angeloc
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:36
帖 子:1353
专家分:0
注 册:2006-11-21
得分:0 

千里,又害我浪费时间!!!下次你快点!


老牛明知夕阳晚,不用扬鞭自奋蹄; Angelo\'s BLOG
2007-01-31 16:25
千里冰封
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:灌水之王
等 级:版主
威 望:155
帖 子:28477
专家分:59
注 册:2006-2-26
得分:0 



可惜不是你,陪我到最后
2007-01-31 16:41
风月_无边
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:60
帖 子:2959
专家分:652
注 册:2007-1-19
得分:0 
以下是引用angeloc在2007-1-31 16:25:01的发言:

千里,又害我浪费时间!!!下次你快点!

其实只要是没人管,最后千里会管的,他是斑竹


我的网站 http://www.
2007-01-31 17:11
千里冰封
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:灌水之王
等 级:版主
威 望:155
帖 子:28477
专家分:59
注 册:2006-2-26
得分:0 
我只是希望对大家有些帮助

没有白来这个版


可惜不是你,陪我到最后
2007-01-31 19:03
chengsencs
Rank: 1
等 级:新手上路
帖 子:109
专家分:0
注 册:2006-7-24
得分:0 

2007-01-31 20:21
千里冰封
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:灌水之王
等 级:版主
威 望:155
帖 子:28477
专家分:59
注 册:2006-2-26
得分:0 
不要光举指头啊,理解了么?

可惜不是你,陪我到最后
2007-01-31 20:25
mickboy
Rank: 1
等 级:新手上路
帖 子:60
专家分:0
注 册:2007-1-11
得分:0 
我学JAVA这么久,居然没有理解调用的先后顺序,今天算是搞明白了~谢谢斑竹了
2007-02-01 01:19



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-119019-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.042779 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved