수입 된 Java 클래스의 공개 정적 최종 변수
문제
나는 내 직장에서 Java 코드를 발견하게된다. 시나리오는 다음과 같습니다. 2 개의 클래스가 있습니다. ClassA
그리고 ClassB
.
ClassA
그 안에는 4 개의 공개 정적 최종 문자열 값을 제외하고는 없습니다. 그 목적은 그와 같은 값을 사용하는 것입니다 ClassA.variable
(왜 내 코드가 아닌지 묻지 마십시오).
ClassB
수입 ClassA
. 문자열 값을 편집했습니다 ClassA
그리고 그것을 편집했습니다. 내가 달렸을 때 ClassB
새로운 값이 아닌 이전 값을 사용하는 것을 볼 수있었습니다. 나는 다시 컴파일해야했다 ClassB
새로운 값을 사용하게합니다 ClassA
! (수입하는 다른 클래스를 다시 컴파일해야했습니다 ClassA
!)
이것은 JDK 1.6 때문입니까, 아니면 이전에 다시 컴파일하는 것을 알고 있었을 것입니다. ClassB
또한! 나를 깨달으십시오. :)
해결책
값의 값이 있다면 final
클래스의 변수 ClassA
컴파일 타임 상수가되면 컴파일러가이를 사용하여 클래스에 상환했을 수 있습니다. 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);
}
}
이 예에서 컴파일러는 FOO
생성 된 코드로 Consumer
동등한 런타임 참조를 생성하는 대신. 값의 경우 FOO
나중에 변경하면 다시 컴파일해야합니다 Consumer
새 값을 사용하기 위해.
이것은 최적화로, 컴파일 된 프로그램의 효율성과 속도와 관련하여 몇 가지 장점이 있습니다. 예를 들어, 값을 인화하는 값은 예를 들어 다음과 같은 표현식에서 추가 최적화를 가능하게 할 수 있습니다.
int x = Flags.FOO * 10;
이 예에서 값을 인화하면 (여기 : 1), 컴파일러가 곱셈이 차이가없고, alltogether를 생략 할 수 있음을 알 수 있습니다.
다른 팁
이진 호환 문제입니다. 상수 필드에 대한 참조는 컴파일 시간에 해결됩니다. 당신이보고있는 행동은 옳습니다. 클래스 A의 값을 변경하면 클라이언트 (클래스 B)를 다시 컴파일해야합니다. 이러한 문제를 피하려면 Java 릴리스 5.0에 도입 된 열거 유형을 사용하여 상수를 추가하는 것을 고려하십시오.
왜 수업을 개별적으로 컴파일하려고합니까?
Maven 또는 Ant와 같은 빌드 시스템을 사용하거나 IDE가 수행하도록하십시오.
해야 할 유일한 안전한 일은 자바 클래스에 의존하는 모든 Java를 다시 컴파일하는 것입니다.
스위치에서 값을 사용하지 않는 경우 대신이 작업을 수행 할 수 있습니다.
public class A
{
public static final int FOO;
public static final String BAR;
static
{
FOO = 42;
BAR = "Hello, World!";
}
}
컴파일러는 더 이상 사용중인 다른 클래스의 값을 하드 코드하지 않습니다.
classa가 다음과 같이 보인다고 가정합니다.
public class ClassA {
public static final int FOO = 1;
public static final int BAR = 2;
}
다시 컴파일하면 ClassB는 이전 값을 계속 사용합니다. 컴파일러에 의존 할 수 있다고 생각하지만 이것이 일반적인 동작이라고 생각합니다. Classa의 상수가 변경 될 때마다 ClassB를 다시 컴파일하지 않으려면 다음과 같은 작업을 수행해야합니다.
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) 메소드를 호출합니다.