今天看到的一个程序,很晕!!
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
为什么输出的顺序是这样的?
能不能详细的解释一下?
谢谢。
----------------解决方案--------------------------------------------------------
今天看到的一个程序,很晕!!
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
----------------解决方案--------------------------------------------------------
首先从程序入口看
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
----------------解决方案--------------------------------------------------------
千里,又害我浪费时间!!!下次你快点!
----------------解决方案--------------------------------------------------------
----------------解决方案--------------------------------------------------------
千里,又害我浪费时间!!!下次你快点!
其实只要是没人管,最后千里会管的,他是斑竹
----------------解决方案--------------------------------------------------------
我只是希望对大家有些帮助
没有白来这个版
----------------解决方案--------------------------------------------------------
----------------解决方案--------------------------------------------------------
不要光举指头啊,理解了么?
----------------解决方案--------------------------------------------------------
我学JAVA这么久,居然没有理解调用的先后顺序,今天算是搞明白了~谢谢斑竹了
----------------解决方案--------------------------------------------------------