public class Test {
static int i = 20; public Test() {
System.err.println("new");
} static {
int i = 10;
System.err.println("static");
} public static void main(String[] args) {
Test a = new Test();
System.out.println(a.i);
}
}昨天看见的一道题,我以为执行的结果是
static
10
new谁知道运行一看我很郁闷:
下面是我运行的结果:
第一次运行:
static
20
new第二次运行的结果:
static
new
20第三次:static20可以得出结论的是static 块比构造方法先执行。但是关于打印那部分不知道怎么解释......new
static int i = 20; public Test() {
System.err.println("new");
} static {
int i = 10;
System.err.println("static");
} public static void main(String[] args) {
Test a = new Test();
System.out.println(a.i);
}
}昨天看见的一道题,我以为执行的结果是
static
10
new谁知道运行一看我很郁闷:
下面是我运行的结果:
第一次运行:
static
20
new第二次运行的结果:
static
new
20第三次:static20可以得出结论的是static 块比构造方法先执行。但是关于打印那部分不知道怎么解释......new
解决方案 »
- 集合hashmap应用根据学号查询学生的信息,查询的结果错误是学生不存在,怎么查到学生的信息呢?刚学java见笑了,请各位帮忙下,能解释下错误的地方更好代码如下
- JPANEL和PANEL有什么不用,为什么在PANEL上画图没问题,变成JPANEL就不显示了?
- 最简单的问题
- 设计一个通过键盘控制物品移动的程序
- NULLpointerException的错误,请帮忙解决下,我是新手,谢谢
- 看得多了却有点理不出个头绪了 关于java环境
- jpanel可见部份
- 一个程序不停的写一个文件,越来越大。怎样把以前的数据拷出来然后把他们从文件里删去?
- 谁能说说cocoon的应用
- java语言修改Windows桌面背景
- executeBatch() 报数组越界错误
- 简单解释一下wait()和notify()吧。。
= 1 =====================
static
new
20
= 2 =====================
20
static
new
= 3 =====================
static
20new
==============================
static 在 new之前是可以确定的
static在类加载的时候print的
new在构造时候print的
至于20就不清楚了,等待高手
static int i = 20; public Test() {
System.out.println("new");
} static {
int i = 10;
System.out.println("static");
} public static void main(String[] args) {
Test a = new Test();
System.out.println(a.i);
}
}
http://fishermen.javaeye.com/blog/24025
这里要注意:
a、不管静态域声明语句的实际位置在哪儿,当第一次加载类的时候都会首先对它初始化为缺省值(0,false,null等)。
b、即使静态域声明中使用了显式初始化语句(比如:int x=3),第一次加载类的时候也会先把它初始化为缺省值(此时x为0),然后再按照下面说的要点c来执行赋值语句(x=3)。
c、对于静态域的显式初始化语句和静态块,按照在类中代码出现的先后顺序执行。
因此,在上面的例子程序中,我们看到
static int s_a=1;
static
{
s_a=11;
s_b=22;
}
static int s_b=2;
对s_a,s_b会有不同的效果。类加载时候,s_a,s_b都被初始化为0,然后由于依照代码顺序执行了s_a=1;s_a=11;s_b=22;s_b=2;结果s_a、s_b分别变成了11和2。 2、当构造类实例时候,会先对实例域初始化为缺省值,然后执行实例块(用{}括起来的部分),然后执行构造方法。其中:
a、如同1中一样,如果有实例域的显式初始化语句,程序仍然是先将该域初始化为缺省值,然后按照代码在类中出现的先后顺序执行初始化语句或者实例块。如果实例块位置在初始化语句前面,即使它改变了该域的值,也会被随后执行的初始化语句改回去。
b、在进入构造方法后,如果构造方法第一句是使用this(...)调用另一构造方法的话,则先执行另一构造方法,然后再执行本构造方法的方法体。这种用法必须让this(...)位于第一句。 《Core java 2》书中所说的"进入构造方法后,如果第一句是调用别的构造方法,则进入别的构造方法。否则,执行实例块"的提法有问题。事实是,不管是否使用this()都会先执行实例块,再进入构造方法。另外,本程序需要在sdk1.4下编译,在sdk1.3下编译将不允许在静态块或实例块中改变位置在它们后面声明的域的值。
1 每个类初始化时,会先初始化它的static再执行构造方法,当static已经执行过后,该类的新的实例不会再执行static
2 该类如果继承了某个类则父类的static会先初始化。
3 某个类即便有static main方法,并且该类作为执行类,因此,可以得到如下顺序:
* 1 父类static 变量/代码块 初始化(即使父类static是private的也会初始化,只会初始化一次)
* 2 子类static 变量/代码块 初始化
* 3 父类构造方法
* 4 子类构造方法
* static变量和static代码块的初始化顺序按照书写的先后顺序初始化
如果静态块那里的int i=10写成i=10就相同了
至于为什么先答应20再打印new我也很纳闷
第一次:
static
new
v
第二次:
20
static
new
关于20不理解,等待高手指点。
我也测试了下,结果:
第一次:
static
new
20
第二次:
20
static
new
关于20不理解,等待高手指点。
当然是20,那个“i=10”的赋值,是对一个局部变量i的操作。2、static代码块和构造的先后。
static块是在加载类时被调用,构造是在new一个对象时被调用,当然是static先于构造。3、顺序。
同一个流(err)输出的顺序是不会变的,所以static肯定在new之前。out和err是2个流,哪个先把数据流到指定的地方(如控制台)都有可能,和多线程差不多。所以20可能在static之前,可能在new之后,还可能在二者之间。而且因为println的换行和正文是分2次流出,所以20的前后可能还没换行就有static或new。
20
static
new跟我想的完全不一样,我汗死…………
规律也总是static new 20而执行程序时却又规律不同了两种情况我都试了很多次,不是巧合问题郁闷了
static 20 new
不过要是把system.err.println换成system.out.println就只有static new 20这一种结果。
不太懂为什么。
重新定义了一个局部变量而已跟原来的i根本没关系原来的i当然是20啦
err是需缓冲的,所以打印结果不一样可以理解
.limit locals 1
.line 4
bipush 20
putstatic src/Test.i I ;static int i=20;
.line 11
bipush 10
istore_0 ; met001_slot000 {int i=10;}
.line 12met001_8: ; DATA XREF: met001_slot000i
getstatic java/lang/System.err Ljava/io/PrintStream;
ldc "static"
invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V
.line 3
return
met001_end: ; DATA XREF: met001_slot000i
;met001_slot000 ; DATA XREF: <clinit>+7w
.var 0 is i I from met001_8 to met001_end
.end methodstatic {statements}这种形式,我理解为声明一个包含statements的对象,所以它们都在<clinit>方法里,而构造函数是<init>,后于<clinit>运行.至于第二个输出先后的问题,由于(参考jdk源代码)
public final static PrintStream err
public final static PrintStream out
它们是两个流变量
而PrintStream中println除了无参数的那个版本外,重载的其他版本都使用了synchronized机制,所以这牵涉到java里的多线程问题.....具体细节就没继续看了.....
运行了N次 觉得这还是跟线程有关,实际的运行顺序就是: static new 20 ,之所以打印顺序不同,那是因为我们被表面现象所迷惑了,System.err跟System.out调用的都是println方法,再看看println()方法:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
} public void println(int x) {
synchronized (this) {
print(x);
newLine();
}
}
原因由此可见。
感谢prog_6103 ,本以为盖棺定论了,谢谢你的提醒。