Java에서 static 정적 변수의 초기화 완전 해석

8686 단어 Javastatic
정적 변수 초기화 순서
1. 간단한 규칙
먼저 가장 보편적인 JAVA 코드를 살펴보겠습니다.

public class Test
{
 public static Test1 t = new Test1();
 public static int a = 0;
 public static int b;

 public static void main(String[] arg)
 {
  System.out.println(Test.a);
  System.out.println(Test.b);
 }
}

class Test1
{
 public Test1()
 {
  Test.a++;
  Test.b++;
 }
}

여기 콘솔 출력 결과가 뭔지 맞혀볼까요?
OK, 혹시 아래의 결과를 알아맞혔을지도 몰라. 그럼 자바에 익숙해져.
0 1
만약 네가 왜 위의 결과를 출력했는지 모르겠다면, 내가 너에게 알려줄게.
Java 정적 변수 초기화는 다음 규칙을 따릅니다.
  • 정적 변수는 선언된 순서에 따라 이 유형의 기본값으로 선언되고 설정되지만 초기화된 값으로 설정되지 않습니다..
  • 성명이 끝난 후 성명의 순서에 따라 초기화된 값으로 설정하고 초기화된 값이 없으면 건너뜁니다
  • 이것을 보면 알 수 있구나, 원래 Test.a의 값이 세 번 변했다.
    선언할 때 0>>Test1: Test1에서 1>>Test로 설정합니다.a 초기화는 0
    2. 복잡한 규칙
    알겠습니다. 아래의 코드를 다시 보십시오.
    
    public class A
    {
     public static int b = B.a;
     public static A plus =new A("A");
     public static final int finalInt = (int)(Math.random()*100);
     public static B p = new B("A");
    
     public static final String finalStr = "finalStr";
     public static final Integer finalInteger = new Integer(10);
     public static int a = 1;
     public static B c = null;
    
     public A(String from)
     {
      System.out.println("----------- begin A::A ----------------");
      System.out.println("A::A, from="+from);
      System.out.println("A::A, A.b="+A.b);
      System.out.println("A::A, A.finalInt="+A.finalInt);
      System.out.println("A::A, B.a="+B.a);
      System.out.println("A::A, B.plus="+B.plus);
      System.out.println("----------- end A::A ----------------");
     }
    
     public static void main(String[] arg)
     {
      System.out.println("main, A.b="+A.b);
      System.out.println("main, B.t="+B.t);
      System.out.println("main, C.a="+C.a);
     }
    }
    
    class B
    {
     public static int t = A.a;
     public static A plus = new A("B");
     public static int a = 1;
    
     public B(String from)
     {
      System.out.println("----------- begin B::B ----------------");
      System.out.println("B::B, from="+from);
      System.out.println("B::B, B.a="+B.a);
      System.out.println("B::B, A.a="+A.a);
      System.out.println("B::B, A.p="+A.p);
      System.out.println("B::B, A.plus="+A.plus);
      System.out.println("B::B, A.finalInt="+A.finalInt);
      System.out.println("B::B, A.finalInteger="+A.finalInteger);
      System.out.println("B::B, A.finalStr="+A.finalStr);
      System.out.println("----------- end B::B ----------------");
     }
    }
    
    class C
    {
     public static final A a = new A("C");
    }
    
    
    이것 괜찮아요?나는 테스트를 하면서 썼기 때문에 알아맞히지 못했다.하하
    콘솔 출력 결과:
    
    ----------- begin A::A ----------------
    A::A, from=B
    A::A, A.b=0
    A::A, A.finalInt=0
    A::A, B.a=0
    A::A, B.plus=null
    ----------- end A::A ----------------
    ----------- begin A::A ----------------
    A::A, from=A
    A::A, A.b=1
    A::A, A.finalInt=0
    A::A, B.a=1
    A::A, B.plus=A@a90653
    ----------- end A::A ----------------
    ----------- begin B::B ----------------
    B::B, from=A
    B::B, B.a=1
    B::B, A.a=0
    B::B, A.p=null
    B::B, A.plus=A@1fb8ee3
    B::B, A.finalInt=61
    B::B, A.finalInteger=null
    B::B, A.finalStr=finalStr
    ----------- end B::B ----------------
    main, A.b=1
    main, B.t=0
    ----------- begin A::A ----------------
    A::A, from=C
    A::A, A.b=1
    A::A, A.finalInt=61
    A::A, B.a=1
    A::A, B.plus=A@a90653
    ----------- end A::A ----------------
    main, C.a=A@61de33
    
    이 결과는 네가 알아맞히지 못했지, 하하.
    프로그램의 실행 결과를 한마디 한마디로 설명하려면 그래도 매우 적절한 편폭을 가져야 한다.자바 정적 변수 초기화에 따른 규칙을 직접 작성합니다.
    첫 번째 단락의 규칙은 여전히 유효하지만, 단지 건전하지 않을 뿐이다.
  • 하나의 클래스를 주동적으로 요청해야만 이 클래스는 초기화되고 정적 변수, 함수, 등 정적 것만 포함한다
  • 계승 관계를 할 때 먼저 부류를 초기화하고 나중에 자류를 초기화한다
  • 정적 변수는 성명의 순서에 따라 먼저 성명하고 이 유형의 기본값으로 설정하지만 초기화된 값은 지정하지 않습니다
  • 성명이 끝난 후에 성명의 순서에 따라 초기화된 값으로 설정하고 초기화된 값이 없으면 건너뜁니다
  • A.b=B.a를 초기화할 때 A.b 초기화를 일시 중지하고 현재 클래스를 B로 설정하고 3단계로 이동하여 실행합니다
  • B.plus = new A를 초기화할 때 B.plus 초기화를 멈추고 실례화 A를 B.plus에 부여합니다.
  • A의 구조 함수에서 B.a의 값을 얻어야 할 때 B.a는 초기화되고 초기화를 잠시 중지한 상태입니다. B.a의 현재 값을 직접 취하고 B.a의 초기화를 기다리지 않습니다
  • final, 정적 상량은 사실 일반 정적 변수의 초기화를 따르지만 컴파일할 때 컴파일러는 변하지 않는 상량 값을 사용하는 곳에서 교체합니다.Java 역컴파일 도구로 볼 수 있습니다.
  • static 데이터의 초기화
    게다가static한정된 필드는 이른바 클래스 필드입니다. 즉, 이 필드의 소유자는 대상이 아니라 클래스입니다.얼마나 많은 대상을 만들든지 간에static 데이터는 하나밖에 없습니다.
    클래스 내에서는 항상 static 필드를 초기화하고 일반 필드를 초기화합니다.이어서 구조기를 초기화하다.그러나 이 클래스의 대상을 만들지 않으면 이 대상은 초기화되지 않고 한 번만 실행됩니다.
    아래 코드와 같이 StaticInitialization 클래스에서 static Table table = new Table () 을 초기화합니다.그런 다음 Table 객체를 초기화합니다. 그렇지 않으면 초기화되지 않습니다.
    
    class Bowl {
     Bowl(int marker) {
     print("Bowl(" + marker + ")");
     }
     void f1(int marker) {
     print("f1(" + marker + ")");
     }
    }
    
    class Table {
     static Bowl bowl1 = new Bowl(1);
     Table() {
     print("Table()");
     bowl2.f1(1);
     }
     void f2(int marker) {
     print("f2(" + marker + ")");
     }
     static Bowl bowl2 = new Bowl(2);
    }
    
    class Cupboard {
     Bowl bowl3 = new Bowl(3);
     static Bowl bowl4 = new Bowl(4);
     Cupboard() {
     print("Cupboard()");
     bowl4.f1(2);
     }
     void f3(int marker) {
     print("f3(" + marker + ")");
     }
     static Bowl bowl5 = new Bowl(5);
    }
    
    public class StaticInitialization {
     public static void main(String[] args) {
     print("Creating new Cupboard() in main");
     new Cupboard();
     print("Creating new Cupboard() in main");
     new Cupboard();
     table.f2(1);
     cupboard.f3(1);
     }
     static Table table = new Table();
     static Cupboard cupboard = new Cupboard();
    }
    
    
    출력:
    
    Bowl(1)
    Bowl(2)
    Table()
    f1(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    Cupboard()
    f1(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f1(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f1(2)
    f2(1)
    f3(1)
    
    표시된 정적 초기화 (정적 블록)
    여러 개의 초기화 문장을 하나의static 괄호 안에 싸서 정적 블록이라고 하는데 사실은 여러 개의static를 합쳐서 쓴 것이다. 본질은 같다.객체나 클래스에 처음 액세스하는 필드를 처음 만들 때만 실행되며 한 번만 실행됩니다.
    
    class Cup {
     Cup(int marker) {
     print("Cup(" + marker + ")");
     }
     void f(int marker) {
     print("f(" + marker + ")");
     }
    }
    
    class Cups {
     static Cup cup1;
     static Cup cup2;
     static {
     cup1 = new Cup(1);
     cup2 = new Cup(2);
     }
     Cups() {
     print("Cups()");
     }
    }
    
    public class ExplicitStatic {
     public static void main(String[] args) {
     print("Inside main()");
     Cups.cup1.f(99); // (1)
     }
     // static Cups cups1 = new Cups(); // (2)
     // static Cups cups2 = new Cups(); // (2)
    } 
    
    출력:
    
    Inside main()
    Cup(1)
    Cup(2)
    f(99)
    
    비정적 인스턴스 초기화
    이것은 별로 할 말이 없다. 바로 일반 초기화이다. 순서대로 실행하면 여러 번 실행할 수 있다.
    
    class Mug {
     Mug(int marker) {
     print("Mug(" + marker + ")");
     }
     void f(int marker) {
     print("f(" + marker + ")");
     }
    }
    
    public class Mugs {
     Mug mug1;
     Mug mug2;
     {
     mug1 = new Mug(1);
     mug2 = new Mug(2);
     print("mug1 & mug2 initialized");
     }
     Mugs() {
     print("Mugs()");
     }
     Mugs(int i) {
     print("Mugs(int)");
     }
     public static void main(String[] args) {
     print("Inside main()");
     new Mugs();
     print("new Mugs() completed");
     new Mugs(1);
     print("new Mugs(1) completed");
     }
    }
    
    
    
    Inside main()
    Mug(1)
    Mug(2)
    mug1 & mug2 initialized
    Mugs()
    new Mugs() completed
    Mug(1)
    Mug(2)
    mug1 & mug2 initialized
    Mugs(int)
    new Mugs(1) completed
    
    

    좋은 웹페이지 즐겨찾기