2009-07-24 7 views

答えて

52

私はなぜ知らないが、JLSは非常に明確である:

Discussion 

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

、デフォルトの要素の定義は次のとおりです。

 DefaultValue: 
     default ElementValue 

残念ながら私は新しい言語機能を見つけておきます(EnumsとAnnotations)は、言語仕様を満たしていないと非常に役に立たないコンパイラエラーメッセージを出します。

EDIT:少しgoogleingは、彼らがこのような状況ではNULLを可能にするために主張しているJSR-308でfollowingが見つかりました:

我々が提案するいくつかの可能な異議を注意してください。

以前は不可能だった提案はできません。

プログラマが定義した特別な値は、「初期化されていない」、「なし」を意味していない可能性があります、nullをより良いドキュメントを提供し、自身ヌルなど

提案は、より多くのエラーが発生しやすいです。明示的な値をチェックするのを忘れるよりもnullをチェックするのを忘れるほうがずっと簡単です。

この提案は、標準イディオムをより冗長にするかもしれません。現在、注釈のユーザだけがその特別な値をチェックする必要があります。この提案では、アノテーションを処理する多くのツールが、NULLポインタ例外をスローしないようにフィールドの値がnullかどうかをチェックする必要があります。

最後の2つの点だけが「最初にやらないのはなぜ」と関連していると思います。最後の点は確かに良い点です。注釈プロセッサは、注釈値にnullを付けることを心配する必要はありません。私は、注釈プロセッサや他のフレームワークコードの仕事が、開発者コードを他の方法よりも明確にするためにそのような種類のチェックをしなければならないことが多いようですが、変更を正当化することは確かに難しいでしょう。

41

それはJLSは、この上で非常にあいまいですが、これは、違法であると思われます。

私が試してみて、注釈にクラス属性を持っていたそこに既存のアノテーションを考えるように私の記憶をwrackedが、およびJAXBのAPIから、このいずれかを思い出した:

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

    static final class DEFAULT {}  
} 

あなたは、彼らがきたかを確認することができますヌルと同等のものを保持するためのダミーの静的クラスを定義する必要がありました。

不快です。

+2

はい、同様のことを行います(デフォルトではFoo.classを使用しています)。吸う。 – ripper234

+5

Stringフィールドの場合は、[magic strings](http://en.wikipedia.org/wiki/Magic_string)にアクセスする必要があります。明らかによく知られている反パターンは、よく理解されている言語機能よりも優れています。 –

+2

@TimYates nullが利用可能で、普遍的に理解されている場合、自分の「無価値」の価値を定義する人々を見るために私を殺します。そして今、それは言語自体によって必要とされているのですか?幸いなことに、あなたの "マジックストリング"を公の定数として定義することができます。まだ理想的ではありませんが、少なくとも注釈を探しているコードでは、リテラルを使用する代わりに定数を参照できます。 – spaaarky21

46

は、それは新しいクラスを必要とせず、それがすでに何を意味する、Javaのキーワードです。この

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

を試してみてください。

+6

私はそれが好きです。唯一の問題は、元の質問の文脈では、この答えは型パラメータをサポートしていないことです。 'Class <? extends Foo> bar()default void.null' はコンパイルされません。 – Kariem

+1

void.classは一般的には適用できません:public @interface NoNullDefault {String value()default void.class; } – wjohnson

+0

Groovyの場合、コメントに記載されている場合でもうまく動作します – Vampire

9

もう1つの方法があるようです。

私はこれも好きではありませんが、うまくいく可能性があります。

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

したがって、基本的に空の配列を作成します。これはデフォルト値を許可するようです。

1

nullリテラルは、Java言語仕様hereで定義されているように、定数表現ではありません。

また、Java Language Specification要素の種類が指定されたデフォルト値(§9.7)相応しない場合には、コンパイル時エラーである

言います。

そして、要素型は、要素の値を持つ 見合っていない場合explain what that means

に、コンパイル時エラーが発生します。

  • は、[...]
  • Vが nullではない:要素型Tは、次のいずれかに該当する場合にのみ 要素値Vに見合いました。

その値がnullあるのでそこでここでは、あなたの要素の種類、Class<? extends Foo>は、デフォルト値に見合っていません。

+0

私は間違っていますか? –

+0

あなたのソリューションはコピー&ペーストには適していません; –

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

述べたように、Java言語仕様では、注釈はデフォルトでnull値を許可していません。

私がするべきことは、DEFAULT_VALUEの定数定義をアノテーション定義の先頭に定義することです。何かのように:私のコードで次に

public static final String DEFAULT_VALUE = "__class-name-here__ default"; 

public String prefix() default DEFAULT_VALUE; 

私のようなものを実行します。クラスであなたの場合

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

を、私はちょうどマーカークラスを定義します。

Class<? extends Foo> bar() default DefaultFoo.class; 

コードを実行できるように、あなたのDefaultFooクラスがするのと同じ空の実装:残念ながら、あなたはとても代わりにあなたのような何かをする必要があり、このための定数を持つことはできません

if (myAnnotation.bar() == DefaultFoo.class) { ... } 

希望これを他の人を助ける。

関連する問題