Program Tip

주석 필드의 기본 null 값을 설정하는 동안 오류가 발생했습니다.

programtip 2020. 11. 3. 18:54
반응형

주석 필드의 기본 null 값을 설정하는 동안 오류가 발생했습니다.


"속성 값은 상수 여야합니다."라는 오류가 발생하는 이유는 무엇입니까? null 상수 가 아닙니까 ???

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
    Class<? extends Foo> bar() default null;// this doesn't compile
}

이유는 모르겠지만 JLS 는 매우 명확합니다.

 Discussion

 Note that null is not a legal element value for any element type. 

기본 요소의 정의는 다음과 같습니다.

     DefaultValue:
         default ElementValue

불행히도 새로운 언어 기능 (Enums 및 현재 Annotations)에는 언어 사양을 충족하지 않을 때 매우 도움이되지 않는 컴파일러 오류 메시지가 있습니다.

편집 : 약간의 googleing 이 JSR-308에서 다음발견 했습니다.이 상황에서 null을 허용한다고 주장합니다.

제안에 대해 몇 가지 이의가있을 수 있습니다.

이 제안은 이전에는 불가능했던 어떤 것도 가능하게하지 않습니다.

프로그래머가 정의한 특수 값은 "없음", "초기화되지 않음", null 자체 등을 의미 할 수있는 null보다 더 나은 문서를 제공합니다.

이 제안은 오류가 발생하기 쉽습니다. 명시 적 값 확인을 잊어 버리는 것보다 null 검사를 잊어 버리는 것이 훨씬 쉽습니다.

제안은 표준 관용구를 더 장황하게 만들 수 있습니다. 현재 주석 사용자 만 특수 값을 확인하면됩니다. 제안을 통해 어노테이션을 처리하는 많은 도구는 널 포인터 예외가 발생하지 않도록 필드의 값이 널인지 여부를 확인해야합니다.

나는 마지막 두 점만이 "처음에 그것을하지 않는 이유"와 관련이 있다고 생각한다. 마지막 요점은 확실히 좋은 점을 제시합니다. 주석 프로세서는 주석 값에 대해 null을 얻을 것이라고 걱정할 필요가 없습니다. 나는 주석 프로세서와 다른 프레임 워크 코드가 개발자의 코드를 다른 방법보다 명확하게 만들기 위해 그런 종류의 검사를해야하는 일이 더 많다고 보는 경향이 있지만, 그것을 변경하는 것을 정당화하기는 확실히 어렵습니다.


이 시도

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
    Class bar() default void.class;
}

새 클래스가 필요하지 않으며 이미 아무 의미가없는 Java의 키워드입니다.


JLS가 이것에 대해 매우 모호하지만 이것은 불법으로 보일 것입니다.

주석에 대한 Class 속성이있는 기존 주석을 생각하기 위해 기억을 곤두 세우고 JAXB API에서이 주석을 기억했습니다.

@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER})        
public @interface XmlJavaTypeAdapter {
    Class type() default DEFAULT.class;

    static final class DEFAULT {}    
}

null과 동등한 것을 보유하기 위해 더미 정적 클래스를 어떻게 정의해야했는지 알 수 있습니다.

불쾌한.


한 가지 다른 방법이있는 것 같습니다.

나는 이것도 좋아하지 않지만 작동 할 수 있습니다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
    Class<? extends Foo>[] bar() default {};
}

따라서 기본적으로 대신 빈 배열을 만듭니다. 이것은 기본값을 허용하는 것 같습니다.


Class<? extends Foo> bar() default null;// this doesn't compile

언급했듯이 Java 언어 사양은 주석 기본값에서 null 값을 허용하지 않습니다.

내가하는 경향 DEFAULT_VALUE은 주석 정의 맨 위에 상수를 정의하는 것입니다. 다음과 같은 것 :

public @interface MyAnnotation {
    public static final String DEFAULT_PREFIX = "__class-name-here__ default";
    ...
    public String prefix() default DEFAULT_PREFIX;
}

그런 다음 내 코드에서 다음과 같은 작업을 수행합니다.

if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_PREFIX)) { ... }

클래스의 경우 마커 클래스를 정의합니다. 불행히도 이에 대한 상수를 가질 수 없으므로 대신 다음과 같은 작업을 수행해야합니다.

public @interface MyAnnotation {
    public static Class<? extends Foo> DEFAULT_BAR = DefaultBar.class;
    ...
    Class<? extends Foo> bar() default DEFAULT_BAR;
}

귀하의 DefaultFoo클래스는 빈 구현은 그렇게 코드가 할 수있는 것 :

if (myAnnotation.bar() == MyAnnotation.DEFAULT_BAR) { ... }

도움이 되었기를 바랍니다.


That error message is misleading, but, no, the null literal is not a constant expression, as defined in the Java Language Specification, here.

Moreover, the Java Language Specification says

It is a compile-time error if the type of the element is not commensurate (§9.7) with the default value specified.

And to explain what that means

It is a compile-time error if the element type is not commensurate with the element value. An element type T is commensurate with an element value V if and only if one of the following is true:

  • T is an array type E[], and either:
    • [...]
  • T is not an array type, and the type of V is assignment compatible (§5.2) with T, and:
    • If T is a primitive type or String, then V is a constant expression (§15.28).
    • If T is Class or an invocation of Class (§4.5), then V is a class literal (§15.8.2).
    • If T is an enum type (§8.9), then V is an enum constant (§8.9.1).
    • V is not null.

So here, your element type, Class<? extends Foo>, is not commensurate with the default value, because that value is null.

참고URL : https://stackoverflow.com/questions/1178104/error-setting-a-default-null-value-for-an-annotations-field

반응형