어노테이션의 요소는 항상 상수여야 하는가?(컴파일 타임 상수)
어노테이션에 Enum 값 사용하기
어노테이션에 Enum을 통해 String 값을 넣으면 이런 에러를 마주친다.
하지만 value 요소에 직접 String을 넣는 두번째 코드는 에러가 나지 않는다.
왜 같은 String인데 Enum을 사용했을 때 에러가 나는 것일까?
에러 내용을 살펴보자.
Attribute value must be constant
어노테이션의 속성 값은 항상 상수여야 한다라는 뜻이다.
상수라 함은 Java에서 Final로 선언된 값을 의미하며 변경할 수 없는 값을 뜻한다.
왜 String을 그대로 넣으면 변경할 수 없는 값이고 Enum을 통해 String을 넣으면 변경할 수 있는 값이라는 걸까?
어노테이션은 전부 컴파일 타임에 정해지는 값이다.
그렇기에 어노테이션에 사용하는 값들은 런타임에 수정되는 요소이면 안된다.
그러므로 어노테이션의 속성은 항상 상수 상태여야한다.
이러한 상수를 컴파일 타임 상수라고 한다.
그렇다는 말은 Enum을 통해 getName()을 통해 String을 불러오는 방식은 컴파일 타임에 결정되는 것이 아닌 런타임 시간에 결정되므로 사용이 안되는 것이다.
그렇다면 Enum은 왜 런타임에 결정되는걸까?
Enum의 getName()이 작동하는 방식은 Enum이 호출 될 때 Enum의 생성자를 호출해서 name 속성에 값이 추가되어야 getName()이 사용가능한 것이다.
그리고 이 과정은 컴파일 시간에 일어나지 않고 런타임 과정 중에 일어나기 때문에 getName() 자체로는 사용이 불가능한 것이다.
enum DevType{
MOBILE("안드로이드"),
WEB("스프링"),
SERVER("리눅스");
private String krName;
private DevType(String krName){
this.krName = krName;
}
public String getKrName() {
return krName;
}
}
간단한 Enum 코드다.
즉, 우리가 Enum을 DevType.MOBILE.getKrName()을 호출하면 그제서야 생성자를 통해 값을 대입시켜서 krName을 가져오는 런타임 동작 방식을 선택하기 때문에 런타임 상수인 것이다.
하지만 DevType.MOBILE.getKrName()은 런타임 시에 결정되는 값이지만 DevType.MOBILE은 컴파일 타임에 결정되는 상수다. 그렇기에 어노테이션이 받을 수 있는 파라미터 타입이 위와 같이 String이 아닌 DevType Enum Type을 직접 받는 형태라면 어노테이션 속성 값에 DevType.MOBILE로 사용이 가능하다.
Enum을 쓰고 싶다면 아래처럼 값을 Final 상수로 한번 더 정제해줘야한다.
그리고 enum.ROLES.USER로 값을 가져와서 사용하면된다.
JVM은 컴파일을 할 당시에 미리 값이 정해져있어야하는 대표적인 요소가 2가지가 있다.
하나는 위의 Annotation이고 하나는 Switch문이다.
Switch
private static final String VALUE_ONE = "value-one"
public static void main(String[] args) {
final String valueTwo = "value" + "-" + "two";
switch (args[0]) {
case VALUE_ONE:
break;
case valueTwo:
break;
}
}
Annotation
private final String deprecatedDate = "20-02-14";
private final String deprecatedTime = "22:00";
@Deprecated(since = deprecatedDate + " " + deprecatedTime)
public void deprecatedMethod() {}
참고
https://www.baeldung.com/java-compile-time-constants#1-compile-time-constants