developer tip

Java의 정적 블록이 실행되지 않음

copycodes 2020. 9. 14. 21:19
반응형

Java의 정적 블록이 실행되지 않음


class Test{
    public static void main(String arg[]){    
        System.out.println("**MAIN METHOD");
        System.out.println(Mno.VAL);//SOP(9090);
        System.out.println(Mno.VAL+100);//SOP(9190);
    }

}

class Mno{
    final static int VAL=9090;
    static{
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

static클래스가로드 될 때 블록이 실행 된다는 것을 알고 있습니다. 그러나이 경우, 인스턴스 변수 내부 클래스 Mno이다 final때문에 그, static블록은 실행되지 않는다.

왜 이렇게이다? 을 제거하면 final제대로 작동합니까?

어떤 메모리가 먼저 할당 됩니까 , static final변수 또는 static블록입니까?

받는 사람에 의한 경우 final액세스 수정 클래스는로드되지 않습니다, 그럼 어떻게 변수 GET 메모리 할 수 있습니까?


  1. static final int필드는 인 컴파일 시간 상수 와 그 값이 원점에 대한 참조없이 대상 클래스로 하드 코딩되고;
  2. 따라서 메인 클래스는 필드를 포함하는 클래스의 로딩을 트리거하지 않습니다.
  3. 따라서 해당 클래스의 정적 초기화 프로그램이 실행되지 않습니다.

구체적으로 컴파일 된 바이트 코드는 다음과 같습니다.

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(9090)
    System.out.println(9190)
}

제거하자마자 final더 이상 컴파일 타임 상수가 아니며 위에서 설명한 특수 동작이 적용되지 않습니다. Mno클래스는 예상대로로드 및 실행하는 초기화 정적된다.


클래스가로드되지 않은 이유 VALfinal AND상수 표현식 (9090)으로 초기화되기 때문입니다 . 이 두 조건이 충족되는 경우에만 상수가 컴파일 시간에 평가되고 필요한 경우 "하드 코딩"됩니다.

컴파일 타임에 표현식이 평가되는 것을 방지하고 JVM이 클래스를로드하도록하려면 다음 중 하나를 수행 할 수 있습니다.

  • 마지막 키워드를 제거하십시오.

    static int VAL = 9090; //not a constant variable any more
    
  • or change the right hand side expression to something non constant (even if the variable is still final):

    final static int VAL = getInt(); //not a constant expression any more
    static int getInt() { return 9090; }
    

If you see generated bytecode using javap -v Test.class, main() comes out like:

public static void main(java.lang.String[]) throws java.lang.Exception;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String **MAIN METHOD
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: sipush        9090
        14: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        17: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        20: sipush        9190
        23: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        26: return        

You can clearly see in "11: sipush 9090" that static final value is directly used, because Mno.VAL is a compile time constant. Therefore it is not required to load Mno class. Hence static block of Mno is not executed.

You can execute the static block by manually loading Mno as below:

class Test{
    public static void main(String arg[]) throws Exception {
        System.out.println("**MAIN METHOD");
        Class.forName("Mno");                 // Load Mno
        System.out.println(Mno.VAL);
        System.out.println(Mno.VAL+100);
    }

}

class Mno{
    final static int VAL=9090;
    static{
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

1)Actually you have not extends that Mno class so when compilation start it will generate constant of variable VAL and when execution start when that variable is needed its load thats from memory.so its not required your class reference so that static bock is not executed.

2)if A class extend that Mno class at that time that static block is included in A class if you do this then that static block is executed. for example.. public class A extends Mno{

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(Mno.VAL);//SOP(9090);
    System.out.println(Mno.VAL+100);//SOP(9190);
}

}

class Mno{
      final static int VAL=9090;
    static`{`
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

As far as I know, it will be executed in order of appearance. For instance :

 public class Statique {
     public static final String value1 = init1();

     static {
         System.out.println("trace middle");
     }
     public static final String value2 = init2();


     public static String init1() {
         System.out.println("trace init1");
         return "1";
     }
     public static String init2() {
         System.out.println("trace init2");
         return "2";
     }
 }

will print

  trace init1
  trace middle
  trace init2

I just tested it and the statics are initialized (=> print) when the class "Statique" is actually used and "executed" in another piece of code (my case I did "new Statique()".

참고URL : https://stackoverflow.com/questions/16853747/static-block-in-java-not-executed

반응형