[java] 개인 최종 정적 속성 대 개인 최종 속성

Java에서는 다음과 같은 차이점이 있습니다.

private final static int NUMBER = 10;

private final int NUMBER = 10;

및는 둘 다 private이며 final, 차이점은 static속성입니다.

더 나은 게 뭐야? 그리고 왜?



답변

일반적으로 static유형인스턴스 가 아닌 유형 자체 와 관련됨”을 의미 합니다.

즉, 유형의 인스턴스를 만들지 않고도 정적 변수를 참조 할 수 있으며 변수를 참조하는 코드는 정확히 동일한 데이터를 참조합니다. 이것을 인스턴스 변수와 비교하십시오.이 경우 클래스의 인스턴스마다 하나의 독립 버전의 변수가 있습니다. 예를 들어 :

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

10 밖으로 인쇄 : y.instanceVariable와는 x.instanceVariable별개로 인해 xy다른 개체를 참조하십시오.

당신은 할 수 는 그렇게 나쁜 생각하지만, 참고 문헌을 통해 정적 멤버를 참조하십시오. 우리가 한 경우 :

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

그러면 20이 출력됩니다-인스턴스 당 하나가 아닌 하나의 변수 만 있습니다. 이것을 다음과 같이 작성하는 것이 더 명확했을 것입니다.

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

그것은 행동을 훨씬 더 분명하게 만듭니다. 최신 IDE는 일반적으로 두 번째 목록을 세 번째 목록으로 변경하도록 제안합니다.

각 인스턴스마다 고유 NUMBER하지만 항상 동일한 값 을 갖기 때문에 다음과 같이 값을 초기화하는 인라인 선언을 가질 이유가 없습니다 (불변이고 리터럴로 초기화 됨). 이것은 final static모든 인스턴스에 대해 하나의 변수 만 갖는 것과 같습니다 .

private final int NUMBER = 10;

따라서 변경할 수없는 경우 인스턴스 당 하나의 사본이있는 지점이 없습니다.

그러나 다음과 같이 생성자에서 초기화되면 의미가 있습니다.

// No initialization when is declared
private final int number;

public MyClass(int n) {
   // The variable can be assigned in the constructor, but then
   // not modified later.
   number = n;
}

이제의 각 인스턴스에 대해 MyClass다르지만 변경할 수없는 값을 가질 수 있습니다 number.


답변

에 대한 최종 초기화 할 때, 그것은 런타임에 다른 값을 할당 할 수 있습니다. 예를 들어

Class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

따라서 각 인스턴스의 필드 값이 다릅니다 습니다 .

들어 정적 최종 , 모든 인스턴스는 동일한 가치를 공유하고, 처음으로 초기화 한 후 변경할 수 없습니다.

Class TestStatic{
      public static final int a;
}

TestStatic t1  = new TestStatic();
t1.a = 10;
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.


답변

static변수 응용 프로그램의 전체 수명 동안 메모리에 숙박, 그리고 클래스 로딩시에 초기화됩니다. 않은 static변수는 컨스마다 초기화되는 new개체. 일반적으로 사용하는 것이 좋습니다 :

private static final int NUMBER = 10;

왜? 이를 통해 인스턴스 당 메모리 사용량이 줄어 듭니다. 캐시 적중에도 유리합니다. 그리고 그것은 의미 static가 있습니다. 특정 유형 (일명 class) 의 모든 인스턴스 (일명 객체)에서 공유되는 것들에 사용해야합니다 .


답변

정적은 “클래스와 연관된”을 의미합니다. 그렇지 않으면 변수가 클래스의 각 인스턴스와 연결됩니다. 정적이라면 메모리에 하나만 있다는 것을 의미합니다. 그렇지 않은 경우 생성 한 각 인스턴스마다 하나씩 있습니다. static은 클래스가로드되는 동안 변수가 메모리에 남아 있음을 의미합니다. 그것 없이는, 인스턴스가있을 때 변수를 gc’d 할 수 있습니다.


답변

답을 읽으면 실제로 진정한 요점을 찾지 못했습니다. 내 2 센트는 다음과 같습니다.

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " +
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " +
                ObjectUtils.identityToString(valueObjectStatic));
    }


    public static void main(final String args[]) {


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

첫 번째 객체에 대한 결과 :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@6c22c95b
final static file address java.io.File@5fd1acd3

두 번째 개체에 대한 결과 :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@3ea981ca
final static file address java.io.File@5fd1acd3

결론 :

자바가 원시 유형과 다른 유형을 구별한다고 생각했습니다. Java의 기본 유형은 문자열 리터럴 (새 문자열 오브젝트가 아님)과 동일하게 항상 “캐시”되므로 정적 멤버와 비 정적 멤버간에 차이가 없습니다.

그러나 비 정적 멤버가 기본 유형의 인스턴스가 아닌 경우 비 정적 멤버에 대한 메모리 복제가 있습니다.

Java가 두 개의 int 변수에 동일한 주소를 제공하므로 valueStatic의 값을 10으로 변경하면 더 나아가게됩니다.


답변

다른 답변은 일반적으로 비 정적 상수를 사용할 이유가 없다는 것을 분명히하는 것처럼 보이지만 상수 변수에 다른 값을 가진 다양한 인스턴스를 가질 수 있음을 지적하는 사람을 찾을 수 없었습니다.

다음 예제를 고려하십시오.

public class TestClass {
    private final static double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

TestClass의 3 개의 인스턴스를 생성하면 하나의 값만 생성되어 정적 상수에 저장되므로 동일한 임의의 값을 세 번 인쇄합니다.

그러나 대신 다음 예제를 시도하면

public class TestClass {
    private final double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

TestClass의 3 개의 인스턴스를 만들면 각 인스턴스마다 임의로 생성 된 상수 값이 있기 때문에 3 개의 다른 임의의 값이 인쇄됩니다.

다른 인스턴스에서 다른 상수 값을 갖는 것이 실제로 유용한 상황은 생각할 수 없지만 정적과 비 정적 결승 사이에 명확한 차이가 있음을 지적하는 데 도움이되기를 바랍니다.


답변

Jon이 말했듯이 클래스 변수라고도하는 정적 변수는 클래스의 인스턴스에 존재하는 변수입니다.

나는 이것에 대한 예를 여기서 발견 했다 .

public class StaticVariable
{
  static int noOfInstances;
  StaticVariable()
  {
    noOfInstances++;
  }
  public static void main(String[] args)
  {
    StaticVariable sv1 = new StaticVariable();
    System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);

    StaticVariable sv2 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);

    StaticVariable sv3 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
    System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
  }
}

프로그램 출력은 다음과 같습니다.

이 예제에서 볼 수 있듯이 각 객체에는 고유 한 클래스 변수 사본이 있습니다.

C:\java>java StaticVariable
No. of instances for sv1 : 1
No. of instances for sv1 : 2
No. of instances for st2 : 2
No. of instances for sv1 : 3
No. of instances for sv2 : 3
No. of instances for sv3 : 3