public class Test
{
public static void main(String[] args){ System.out.println(OK.i); }
}
情况1:
class OK
{
static int i=0;
static { int i=5; }
}
class OK
{
static { int i=5; }
static int i=0;
}
情况3:
class OK
{
static int i=0;
static { i=5; }
}
情况4:
class OK
{
static { i=5; System.out.println(OK.i);}
static int i=0;
}
情况1与2,输出结果相同,都为0;
情况3,输出5;情况4,输出5,0;
============================
说明:
· 第一static{}和static属性的区别,static{} 是类作初始化的一种方式, 可以做很多事情。 比如对象的初始化, 调用别的方法等等。 静态属性, 这是类的一部分, main 方法是输出类的静态属性 , 这点很重要
· 1,2 两种情况很好解释 , 是因为 static{int i=0;} 不是初始化类的属性 , 而就是定义一个变量而已 , 给你换一种写法static{int i=0;int j=i+10;}这 说明什么 ? 就是在这个静态块作计算而已 , 和你的静态属性一点关系没有 , 你搞一个同名的 ? 很混淆视听的 , 不如起不同的名字了
·3,4两种情况更好解释了,这次你是在初始化你的静态属性了,因为static{ i=0},没有int的啊 ,也就是没有定义新的变量,这个i就是你的静态变量。由于jvm处理静态东西是在类的加载一同处理的,就是一个顺序执行的过程,我这样说不知道你明白没有。
以下是对情况 4 的详解:
· 输出的结果是 5,0 ,原因很简单啊,这个东西是顺序执行的,对了,我知道你的问题了 ^&^ 你是后定义静态属性的,但是还能用 static{} 来初始化 ? 好在我看过 jvm 虚机的一些知识。这些类的信息都是放在一个公用的堆栈,当你调用这个类的时候,类的所有信息都已经加载内存里(当然是 jvm 的分配和管辖的,而且就是唯一这一份信息)。
· 所以在你 static 初始化的时候,它已经存在了,因此就是 5 ,当执行 int i=0; 的时候,自然就是 0 了,不过此时执行的是 i=0, 因为实际上这个属性已经在内存了。
· 如果你还不懂话,就需要知道什么时候类加载到内存 , 就是我们通常说的反射中Class类,这个在你每编译一个类的时候,jvm给你做了黑匣子自动放到类的class中。因此最通常是类加载到内存的方法,就 是new 一个对象,还有别的方法,比如调用类的静态方法和静态属性,所以static int i=0;作用是定义一个类的静态属性作用,本应该int=0初始化一番,但是static{}和它优先级一样高,所以顺序执行一番了。
=================以下为构造方法和static混合==================
public class StaticInit
{
static int i;
int a;
public StaticInit()
{
a=6;
System.out.println("a 的初始化"+a);
}
public static void main(String[] args)
{
new StaticInit();
}
static
{
i=5;
System.out.println("i 的初始化"+i);
}
}
输出结果:
i 的初始化5
a 的初始化6
说明:
类应该先运行static方法,应该按顺序运行:
静态成员 -> 静态块 -> 然后再运行非静态成员 最后再运行 构造函数 (一般系统默认运行不带参数的构造函数);
============继承关系的例子(也是运用这种规则)======================
--------Test.java------
public class Test {
static int i = 1;// 对i 赋值
public void method() {
System.out.println("Test-普通方法 " + i);
}
public Test() {
System.out.println("Test-构造方法 " + i);
}
static {
System.out.println("Test-static-first " + i);
i = 4;// 再次赋值,覆盖原值
System.out.println("Test-static-second " + i);
}
}
-----------SubTest.java------------
public class SubTest extends Test {// 继承TestStatic方法
static int n = 2;// 对n赋值
public SubTest() {
System.out.println("SubTest-构造方法 " + n);
}
public static void main(String args[]) {
SubTest t = new SubTest();
t.method();// 调用父类方法
}
static {
System.out.println("SubTest-static-first " + n);
n = 3;// 再次赋值,覆盖原值
System.out.println("SubTest-static-second " + n);
}
}
运行结果:
Test-static-first 1
Test-static-second 4
SubTest-static-first 2
SubTest-static-second 3
Test-构造方法 4
SubTest-构造方法 3
Test-普通方法 4
说明:
首先运行子类的static属性 static int n = 2;但是紧接着static块又为n赋值,又因为n为静态所以n值永远为3;
然后运行main()函数,出现new()方法,因为是子类 初始化父类,i 赋值与n原理相同所以 i输出永远为4;
父类初始化同样按照static -> 非static -> 构造函数,初始化子类,因为子类static部分已经初始化,所以直接非static -> 构造函数 ->继续运行main()中方法。
===========================
如果执行顺序还有其他问题,可以用jdk自带的工具javap 来查看。常用命令: javap -c ClassName