2009-11-07 5 views
18

내 직장에서 Java 코드를 발견하게됩니다. 이 시나리오는 다음과 같습니다. ClassAClassB의 두 클래스가 있습니다.가져온 Java 클래스의 public static final 변수

ClassA에는 그 중 4 개의 static final string 값을 제외하고는 아무 것도 없습니다. 그 목적은 ClassA.variable과 같은 값을 사용하는 것입니다 (왜 내 코드가 아닌지 묻지 마십시오).

ClassB 수입품 ClassA. 문자열 값을 ClassA으로 편집하고 컴파일했습니다. ClassB을 실행했을 때 새로운 값이 아닌 이전 값을 사용하고있는 것을 볼 수있었습니다. 나는 ClassA에서 새로운 값을 사용하도록 ClassB을 다시 컴파일해야했습니다! (ClassA을 가져 오는 다른 클래스를 다시 컴파일해야했습니다!)

JDK 1.6 때문인가요? 아니면 이전에 다시 컴파일해야했는지 알고 있어야합니다 ClassB! 나에게 계몽해라. :)

답변

23

ClassA의 변수 final의 값이 컴파일 타임 상수가되면 컴파일러에서 런타임 참조를 생성하는 대신 ClassA을 사용하여 클래스에 인라인했을 수 있습니다. 내 생각에, 당신이 묘사 한 사건에서 일어난 일입니다.

예이 예에서

public class Flags { 
    public static final int FOO = 1; 
    public static final int BAR = 2; 
} 

public class Consumer { 
    public static void main(String[] args) { 
     System.out.println(Flags.FOO); 
    } 
} 

컴파일러 가능성 대신 해당 실행 시간 레퍼런스를 생성 Consumer 위해 생성 된 코드에 FOO의 값을 포함한다. 나중에 FOO 값이 변경되면 새 값을 사용하려면 Consumer을 다시 컴파일해야합니다.

이것은 최적화 프로그램으로, 컴파일 된 프로그램의 효율성과 속도면에서 몇 가지 장점이 있습니다. (현재 : 1) 값을 인라인,이 예에서는

int x = Flags.FOO * 10; 

예를 들어, 값을 인라인 것은 예를 들어 그것을 사용하는 표현에 더 최적화를 활성화 수도 주목할 컴파일러는 수를 곱하기 만드는 차이는 없으며 모두 생략 할 수 있습니다.

+1

그래서 public static final은 컴파일 타임 상수입니까? 그걸 몰랐어. 그것이 상수라고 생각하고 런타임에 수정할 수 없습니다! 당신의 도움을 주셔서 감사합니다. –

+3

좋은 설명. 변수가 인라인되어 있는지 확인하려면 javap을 사용하여 클래스가 컴파일 된 방식을 볼 수 있습니다. "javap -c Flags". –

3

이진 호환성 문제입니다. 상수 필드에 대한 참조는 컴파일 타임에 해결됩니다. 보고있는 동작이 정확합니다. 클래스 A의 값을 변경하면 클라이언트 (클래스 B)를 다시 컴파일해야합니다. 이러한 문제를 피하려면 Java 릴리스 5.0에서 소개 된 enum 유형을 사용하여 상수를 추가하는 것이 좋습니다.

2

왜 클래스를 개별적으로 컴파일하려고합니까?

maven 또는 ant와 같은 빌드 시스템을 사용하거나 IDE에서 수행하도록하십시오.

할 수있는 모든 클래스가 다시 컴파일 될 때까지 변경된 java 클래스에 따라 달라지는 모든 java를 다시 컴파일하는 것이 안전합니다. 당신이 스위치의 값을 사용하지 않는 경우

+0

하나 또는 다른 클래스가 귀하의 통제하에 있지 않을 수도 있습니다. – DJClayworth

2

대신이 작업을 수행 할 수 있습니다

public class A 
{ 
    public static final int FOO; 
    public static final String BAR; 

    static 
    { 
     FOO = 42; 
     BAR = "Hello, World!"; 
    } 
} 

다음 컴파일러는 더 이상 하드를 사용하고있는 다른 클래스의 값을 코딩하지 않습니다.

2

가정하자를 ClassA는 다음과 같습니다 : 당신이 그것을 다시 컴파일하면

public class ClassA { 
    public static final int FOO = 1; 
    public static final int BAR = 2; 
} 

는, ClassB가 이전 값을 계속 사용합니다. 나는 그것이 컴파일러에 달려 있다고 생각하지만, 이것이 전형적인 행동이라고 생각한다. 당신은 ClassB가에게를 ClassA 변화에 매번 일정을 다시 컴파일하지 않으려면 다음과 같이 뭔가를해야 할 것이다 :

public class ClassA { 
    public static final int FOO = CONST(1); 
    public static final int BAR = CONST(2); 

    public static int CONST(int i) { return i; } 
} 

Becuase 지금 javac의이 상수를 인라인 내키지입니다. 대신 ClassA의 정적 초기화 프로그램이 실행될 때 CONST (int) 메서드를 호출합니다.

관련 문제