public class StaticTest {
public static int k=0;
public static StaticTest s1=new StaticTest("s1");
public static StaticTest s2=new StaticTest("s2");
public static int i=print("i");
public static int n=99;
public int j=print("j");
{
print("构造块");
}
static
{
print("静态块");
}
public static int print(String s)
{
System.out.println(++k+":"+s+"\ti="+i+"\tn="+n);
++n;
return ++i;
}
public StaticTest(String s)
{
System.out.println(++k+":"+s+"\ti="+i+"\tn="+n);
++i;
++n;
}
public static void main(String[] args) {
new StaticTest("init");
}
}
这是去年阿里的一道笔试题,很有难度,百思不得其解; 代码如下: public class StaticTest { public static int k=0; public static StaticTest s1=new StaticTest("s1"); public static StaticTest s2=new StaticTest("s2"); public static int i=print("i"); public static int n=99; public int j=
简单点解释就是:静态变量首先加载,结果在初始化静态变量s1时,调用实例化对象方法。导致s1之后的静态变量初始化暂停,转而初始化实例变量(注:此时静态变量的初始化就暂停了 直接跳到public int j=print("j");)。
所以1-3行输出结果是public static StaticTest s1=new StaticTest("s1");导致。
所以4-6行输出结果是继续初始化静态变量public static StaticTest s2=new StaticTest("s2");导致。
7-8行输出结果为继续初始化静态变量public static int i=print("i");
public static int n=99;
public int j=print("j");导致
9-10行输出结果为main方法内导致!
public class OrdinayClassInitTest {
/**
* 非静态字段
*/
private int k =10;//(1)
private Long longL = 100L;
private long L = 1000L;
/**
* 静态字段
*/
private static int k1 =10;//(2)
private static Long longL1 = 100L;
private static long L1 = 1000L;
static{
System.out.println("本程序运行到了静态代码段!");
}
public static void main(String[] args) {
OrdinayClassInitTest oInitTest = new OrdinayClassInitTest();
}
}
public class OrdinayClassInitTest {
/**
* 非静态字段
*/
private int k =10;//(1)
private Long longL = 100L;
private long L = 1000L;
/**
* 静态字段
*/
private static int k1 =10;//(2)
private static Long longL1 = 100L;
private static long L1 = 1000L;
static{
System.out.println("本程序运行到了静态代码段!");
}
public static void main(String[] args) {
}
}
sorry, I am not sure why you raise the argument on the value on variable n.
I thought we both agree that default value exists for static variables. I might misunderstood you when you said:"嵌套的new不再管静态变量随后的静态变量赋值,并不是因为它们都有了初值,这些初值也并不是在main中的new引发的,而是在初始化之前完成的。".After the second read, I got what you meant. But I would suggest you replacing "初值" with "缺省值",which could completely rule out any misunderstanding...
are we on the same page now?
[quote=引用 39 楼 micropentium6 的回复:]
are you talking to me or qiao_198911?
[quote=引用 35 楼 skyhitnow 的回复:]
[quote=引用 33 楼 micropentium6 的回复:]
the paragraph you referred to is probably out of date, this is the latest JLS:
12.3.2 Preparation of a Class or Interface Type
Preparation involves creating the static fields (class variables and constants) for
a class or interface and initializing such fields to the default values (§4.12.5). This
does not require the execution of any source code; explicit initializers for static
fields are executed as part of initialization (§12.4), not preparation.
See the part was removed: "preparation does not require the execution of any Java virtual machine code"
This piece of verbiage proves that there are default values for static fields in the class during the preparation stage(§4.12.5). However, this particular behavior on this code sample, we only have observation...
[quote=引用 32 楼 skyhitnow 的回复:]
[quote=引用 31 楼 micropentium6 的回复:]
I don't agree with you on this one. Class variable does have it "default value" regardless of the availability of static initializers! As I indicated previously, static variable with primitive type will be given a default value 0, reference type on the other hand, will be "assigned" with null. a good analogy is the implementation of C, the uninitialized variable in .bss segment will be "initialized" by kernel to arithmetic 0 or null pointers.
these static initializers are supposed to be invoked before any class instance is created. However, according to the textual order rule, if the instantiation of a class variable requires invoking instance initializers before the completion of static initializers, this particular instance will be in an "incomplete" status, which means the remaining static variables that is after this class variable will only have their "default value". Of course, this is my understanding but we failed to find this "rule" in official document to support ourselves.
The "初值" you referred to is actually the "initialized variable". It's different from a variable with default value...
my 2cents!
[quote=引用 28 楼 skyhitnow 的回复:]
嵌套的new不再管静态变量随后的静态变量赋值,并不是因为它们都有了初值,这些初值也并不是在main中的new引发的,而是在初始化之前完成的。如果是因为静态变量都已经有了初值而不再理会初始化阶段,那main中的new应该也不会引起类的初始化了。关键的一点是,在未完成初始化的类上调用new,会采取什么行动?我觉得在new任何对象的时候,都会检查该类的初始化状态。如果初始化已经正常完成,那肯定是直接执行实例化阶段了。但是,初始化尚未完成,该怎么办?这是要有定义的,而不是简单的第一次调用new时初始化,如果第一次初始化标示类处于错误状态,那随后的new难道因为它是第二次new就不再查看类的状态,直接去实例化吗?对于其中的细节我没有研究,希望精通的大神讲解一下。
5.4.2 Preparation
Preparation involves creating the static fields for the class or interface and initializing those fields to their standard default values (§2.5.1). Preparation should not be confused with the execution of static initializers (§2.11); unlike execution of static initializers, preparation does not require the execution of any Java virtual machine code.[/quote][/quote]
这不是说明了为什么n是0,而不是99吗?如果初始化完成,它就是99。0这个值当然不是在初始化阶段赋予的。[/quote][/quote]
我当然是和你说,我并没否认你引用的内容,我引用的那段来自jvm规范,它们之间有矛盾吗?[/quote][/quote]
抱歉,我用词却有不妥,意思你已明白,共识算达成了吧。
sorry, I am not sure why you raise the argument on the value on variable n.
I thought we both agree that default value exists for static variables. I might misunderstood you when you said:"嵌套的new不再管静态变量随后的静态变量赋值,并不是因为它们都有了初值,这些初值也并不是在main中的new引发的,而是在初始化之前完成的。".After the second read, I got what you meant. But I would suggest you replacing "初值" with "缺省值",which could completely rule out any misunderstanding...
are we on the same page now?
are you talking to me or qiao_198911?
[quote=引用 35 楼 skyhitnow 的回复:]
[quote=引用 33 楼 micropentium6 的回复:]
the paragraph you referred to is probably out of date, this is the latest JLS:
12.3.2 Preparation of a Class or Interface Type
Preparation involves creating the static fields (class variables and constants) for
a class or interface and initializing such fields to the default values (§4.12.5). This
does not require the execution of any source code; explicit initializers for static
fields are executed as part of initialization (§12.4), not preparation.
See the part was removed: "preparation does not require the execution of any Java virtual machine code"
This piece of verbiage proves that there are default values for static fields in the class during the preparation stage(§4.12.5). However, this particular behavior on this code sample, we only have observation...
[quote=引用 32 楼 skyhitnow 的回复:]
[quote=引用 31 楼 micropentium6 的回复:]
I don't agree with you on this one. Class variable does have it "default value" regardless of the availability of static initializers! As I indicated previously, static variable with primitive type will be given a default value 0, reference type on the other hand, will be "assigned" with null. a good analogy is the implementation of C, the uninitialized variable in .bss segment will be "initialized" by kernel to arithmetic 0 or null pointers.
these static initializers are supposed to be invoked before any class instance is created. However, according to the textual order rule, if the instantiation of a class variable requires invoking instance initializers before the completion of static initializers, this particular instance will be in an "incomplete" status, which means the remaining static variables that is after this class variable will only have their "default value". Of course, this is my understanding but we failed to find this "rule" in official document to support ourselves.
The "初值" you referred to is actually the "initialized variable". It's different from a variable with default value...
my 2cents!
[quote=引用 28 楼 skyhitnow 的回复:]
嵌套的new不再管静态变量随后的静态变量赋值,并不是因为它们都有了初值,这些初值也并不是在main中的new引发的,而是在初始化之前完成的。如果是因为静态变量都已经有了初值而不再理会初始化阶段,那main中的new应该也不会引起类的初始化了。关键的一点是,在未完成初始化的类上调用new,会采取什么行动?我觉得在new任何对象的时候,都会检查该类的初始化状态。如果初始化已经正常完成,那肯定是直接执行实例化阶段了。但是,初始化尚未完成,该怎么办?这是要有定义的,而不是简单的第一次调用new时初始化,如果第一次初始化标示类处于错误状态,那随后的new难道因为它是第二次new就不再查看类的状态,直接去实例化吗?对于其中的细节我没有研究,希望精通的大神讲解一下。
5.4.2 Preparation
Preparation involves creating the static fields for the class or interface and initializing those fields to their standard default values (§2.5.1). Preparation should not be confused with the execution of static initializers (§2.11); unlike execution of static initializers, preparation does not require the execution of any Java virtual machine code.[/quote][/quote]
这不是说明了为什么n是0,而不是99吗?如果初始化完成,它就是99。0这个值当然不是在初始化阶段赋予的。[/quote][/quote]
我当然是和你说,我并没否认你引用的内容,我引用的那段来自jvm规范,它们之间有矛盾吗?[/quote]