探讨static的执行顺序

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; }
}

情况2:
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

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值