2017-12-10 22 views
4

this questionを見て、getまたはsetへの@Throwsの適用は無効です。@ターゲットがプロパティのときには効果がありません

はさらに、@Throwsためのみ有効なターゲットAnnotationTarget.FUNCTIONAnnotationTarget.PROPERTY_GETTERAnnotationTarget.PROPERTY_SETTER、およびAnnotationTarget.CONSTRUCTORです。

JPAアノテーションやDeprecatedなどの他のアノテーションは、このメソッドに正しく適用されています。

これは異常な動作です。

私がデモンストレーションするために、Javaで単純な抽象クラスを作成しました。コンストラクタ、メソッド、getメソッドがそれぞれ1つずつありました。

public abstract class JavaAbstractClass { 

    @Deprecated 
    @NotNull public abstract String getString() throws IOException; 
    public abstract void setString(@NotNull String string) throws IOException; 

    public abstract void throwsFunction() throws IOException; 

    public JavaAbstractClass() throws IOException { 
    } 

} 

あなたが見ることができるように、すべてのメソッド/コンストラクタがIOExceptionを投げるとしてマークされています。

しかし

、私はKotlinの等価クラスを作成し、相互運用のためのthrowsとの適切な方法をマークしようと、生成されたgetStringsetString方法は何throws句を持っていません。

abstract class KotlinAbstractClass @Throws(IOException::class) constructor() { 

    @get:Deprecated("Deprecated") 
    @get:Throws(IOException::class) 
    @set:Throws(IOException::class) 
    abstract var string: String 

    @Throws(IOException::class) 
    abstract fun throwsFunction() 

} 

逆コンパイルコード:

@Metadata(Some metadata here) 
public abstract class KotlinAbstractClass { 
    /** @deprecated */ 
    @Deprecated(
     message = "Deprecated" 
    ) // @Deprecated made it through! 
    @NotNull 
    public abstract String getString(); // Nothing here! 

    public abstract void setString(@NotNull String var1); // Nothing here! 

    public abstract void throwsFunction() throws IOException; 

    public KotlinAbstractClass() throws IOException { 
    } 
} 

私にとって、これらの内部のアノテーションではなくメソッドに直接適用されるので、コンパイラによって特別に扱わなければならないためと考えられます。

また、非抽象プロパティのゲッターにそれを適用する:

val string: String 
@Throws(IOException::class) get() = "Foo" 

は署名public final String getString() throws IOException持つメソッドを生成しません!

このケースは正しく処理されていない可能性がありますか?

これはバグですか?


注:これは、このメソッドが実際にこの例外をスローするかどうかとは関係ありません。

は私が行う場合:

@get:Throws(IOException::class) 
val string: String 
    get() = BufferedReader(FileReader("file.txt")).readText() 

コンパイルされたコードはFileReader constructorFileNotFoundExceptionスローという事実にもかかわらず、まだ

@NotNull 
public final String getString() { 
    return TextStreamsKt.readText((Reader)(new BufferedReader((Reader)(new FileReader("file.txt"))))); 
} 

です。

さらに、抽象メソッドの場合は、実装を行うことができず、throws節を持つことができるため、これは重要ではありません。

私は@tynnが示唆するように行い、具体的な実装を追加した場合:

class ConcreteClass : KotlinAbstractClass() { 

    override val string: String 
     get() = BufferedReader(FileReader("file.txt")).readText() 

    ... 

} 

を、私はまだ同じ結果を得ます。

+0

実際にこの例外をスローするゲッターまたはセッターを実装しようとします。あなたのコードが安全であれば、あなたが上書きするものの 'throws'宣言を再宣言する必要はありません。たぶん_Kotlin_は '@ Throws'アノテーションでちょうど巧妙です。 – tynn

+0

@tynn私は私の質問を編集します。 – Moira

答えて

2

私は@tynnでは、次のかを示していると信じて:

override val string: String 
     @Throws(FileNotFoundException::class) get() = BufferedReader(FileReader("file.txt")).readText() 

これはあなたの署名でthrowsとの適切なバージョンのJavaを与える必要があります。

@get:Throws(IOException::class) 
val foo: String = "foo" 

あなたはそれをオーバーライドしたことがありませんので、コンパイラは、IOExceptionを投げるでしょうゲッターで何もないことを確認するために十分にスマートであるので、それは勝った:私は推論はあなただけのこの操作を行う場合ということですねthrowsセクションを生成します。ゲッターがオーバーライドされると、コンパイラは指定したコードがスローできるかどうかを知る方法がないため、アノテーションに従い、常にthrows部分を出力します。

abstract class KotlinAbstractClass { 

    abstract var string: String 
     @Throws(IOException::class) get 
     @Throws(IOException::class) set 
} 

それを詳しく見て取った後、私はこのケースでは動作しない@get:Throws(IOException::class)ない理由を見ない:

UPDATEは

以下は正しいバイトコードを生成しているようです。あなたはKotlinのYouTrackに問題を提出し、チームメンバーがそれについて何を言わなければならないかを見るかもしれません。

+0

いいえ、私は私の質問で両方の部分に取り組んでいました。 '@ Throws'を_any_ getterに直接置くと、スローされなくても' throws'節が追加されます。 '@get:Throws'を_any_プロパティに置くと(たとえそれが_does_ throwであっても)何の効果もありません。私があなたが提案し、 'val string:String @Throws(IOException :: class)get()=" Foo "'を指定すると、コンパイラは、IOExceptionをスローするゲッターには何もないことを知るのに十分スマートです "スロー句がまだ生成されているため、不可能です。 – Moira

+0

私の答えは、動作するソリューションで更新されました。 – Egor

+1

ああ、私はその可能性について忘れていた。私は使用サイト注釈がうまくいくように思えることに同意します。できるときはそれをします。ありがとう! – Moira

関連する問題