Warum erhalte ich die Fehlermeldung "Attributwert muss konstant sein". Ist nicht Null konstant ???
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeInterface {
Class<? extends Foo> bar() default null;// this doesn't compile
}
java
annotations
default
ripper234
quelle
quelle
Class<? extends Foo> bar();
.Antworten:
Ich weiß nicht warum, aber das JLS ist sehr klar:
Discussion Note that null is not a legal element value for any element type.
Und die Definition eines Standardelements lautet:
DefaultValue: default ElementValue
Leider stelle ich immer wieder fest, dass die neuen Sprachfunktionen (Enums und jetzt Annotations) sehr wenig hilfreiche Compiler-Fehlermeldungen enthalten, wenn Sie die Sprachspezifikation nicht erfüllen.
EDIT: Ein wenig googleing fanden die folgende in der JSR-308, wo sie argumentieren für nulls in dieser Situation erlaubt:
Ich denke, nur die letzten beiden Punkte sind relevant für "warum nicht überhaupt?". Der letzte Punkt bringt sicherlich einen guten Punkt auf den Punkt - ein Annotationsprozessor muss sich niemals Sorgen machen, dass er eine Null für einen Annotationswert erhält. Ich neige dazu, dass es eher die Aufgabe von Annotationsprozessoren und anderem solchen Framework-Code ist, diese Art von Überprüfung durchführen zu müssen, um den Entwicklercode klarer zu machen, als umgekehrt, aber es würde es sicherlich schwierig machen, eine Änderung zu rechtfertigen.
quelle
Versuche dies
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class bar() default void.class; }
Es erfordert keine neue Klasse und es ist bereits ein Schlüsselwort in Java, das nichts bedeutet.
quelle
Class<? extends Foo> bar() default void.null
Kompiliert nicht.Es scheint, dass dies illegal ist, obwohl die JLS diesbezüglich sehr verschwommen ist.
Ich habe mein Gedächtnis zerstört, um zu versuchen, an eine vorhandene Annotation zu denken, die ein Class-Attribut für eine Annotation hatte, und mich an diese aus der JAXB-API erinnert:
@Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER}) public @interface XmlJavaTypeAdapter { Class type() default DEFAULT.class; static final class DEFAULT {} }
Sie können sehen, wie sie eine statische Dummy-Klasse definieren mussten, um das Äquivalent einer Null zu halten.
Unangenehm.
quelle
Es scheint, dass es einen anderen Weg gibt, dies zu tun.
Ich mag das auch nicht, aber es könnte funktionieren.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class<? extends Foo>[] bar() default {}; }
Im Grunde genommen erstellen Sie stattdessen ein leeres Array. Dies scheint einen Standardwert zuzulassen.
quelle
Wie bereits erwähnt, erlaubt die Java-Sprachspezifikation keine Nullwerte in den Annotationsstandards.
Ich neige dazu,
DEFAULT_VALUE
Konstanten oben in der Annotationsdefinition zu definieren. Etwas wie:public @interface MyAnnotation { public static final String DEFAULT_PREFIX = "__class-name-here__ default"; ... public String prefix() default DEFAULT_PREFIX; }
Dann mache ich in meinem Code so etwas wie:
if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_PREFIX)) { ... }
In Ihrem Fall mit einer Klasse würde ich nur eine Markierungsklasse definieren. Leider können Sie dafür keine Konstante haben. Stattdessen müssen Sie Folgendes tun:
public @interface MyAnnotation { public static Class<? extends Foo> DEFAULT_BAR = DefaultBar.class; ... Class<? extends Foo> bar() default DEFAULT_BAR; }
Ihre
DefaultFoo
Klasse wäre nur eine leere Implementierung, damit der Code Folgendes tun kann:if (myAnnotation.bar() == MyAnnotation.DEFAULT_BAR) { ... }
Hoffe das hilft.
quelle
.equals()
und nicht==
? Haben Sie einen anderen Wert oder ein anderes Objekt erhalten?==
..equals()
. Überraschend.Diese Fehlermeldung ist irreführend, aber nein, das
null
Literal ist kein konstanter Ausdruck, wie in der Java-Sprachspezifikation hier definiert .Darüber hinaus ist die Java Language Specification sagt
Und um zu erklären, was das bedeutet
Hier entspricht Ihr Elementtyp
Class<? extends Foo>
also nicht dem Standardwert, da dieser Wert istnull
.quelle
or
und ein Inneresand
, die nicht ausgelassen werden dürfen.Wie andere gesagt haben, gibt es eine Regel, die besagt, dass null in Java kein gültiger Standardwert ist.
Wenn Sie eine begrenzte Anzahl möglicher Werte für das Feld haben , können Sie dies umgehen, indem Sie den Feldtyp zu einer benutzerdefinierten Aufzählung machen, die selbst eine Zuordnung zu null enthält. Stellen Sie sich zum Beispiel vor, ich habe die folgende Anmerkung, für die ich eine Standard-Null haben möchte:
public @interface MyAnnotation { Class<?> value() default null; }
Wie wir festgestellt haben, ist dies nicht zulässig. Was wir stattdessen tun können, ist eine Aufzählung zu definieren:
public enum MyClassEnum { NULL(null), MY_CLASS1(MyClass1.class), MY_CLASS2(MyClass2.class), ; public final Class<?> myClass; MyClassEnum(Class<?> aClass) { myClass = aClass; } }
und ändern Sie die Anmerkung als solche:
public @interface MyAnnotation { MyClassEnum value() default MyClassEnum.NULL; }
Der Hauptnachteil davon (abgesehen davon, dass Sie Ihre möglichen Werte aufzählen müssen) ist, dass Sie Ihren Wert jetzt in eine Aufzählung eingeschlossen haben, sodass Sie die Eigenschaft / den Getter in der Aufzählung aufrufen müssen, um den Wert zu erhalten.
quelle