@Throws не влияет, когда цель является свойством

@Throws к этому вопросу , я заметил, что применение @Throws к @Throws get или set не имеет никакого эффекта.

Кроме того, единственными действительными целями для @Throws являются AnnotationTarget.FUNCTION , AnnotationTarget.PROPERTY_GETTER , AnnotationTarget.PROPERTY_SETTER и AnnotationTarget.CONSTRUCTOR .

Другие аннотации, такие как аннотации JPA, а также Deprecated работы и правильное применение к методу!

Это странное поведение.

Чтобы продемонстрировать, я создал простой абстрактный класс в Java, с одним конструктором, одним методом и одним методом get.

 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 для interop, сгенерированные методы getString и setString не имеют предложения setString .

 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() 

Скомпилированный код по-прежнему

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

несмотря на то, что конструктор FileReader FileNotFoundException .

Кроме того, это не имеет значения для абстрактных методов в любом случае, поскольку они не могут иметь реализацию и все еще могут иметь предложение throws .

Если я сделаю так, как @tynn предлагает и добавить конкретную реализацию:

 class ConcreteClass : KotlinAbstractClass() { override val string: String get() = BufferedReader(FileReader("file.txt")).readText() ... } 

Я все равно получаю тот же результат.

Я считаю, что @tynn предлагает вам сделать следующее:

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

Это должно дать вам правильную версию Java с throws в подписи. Я предполагаю, что рассуждение состоит в том, что если вы просто сделаете это:

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

компилятор достаточно умен, чтобы убедиться, что в getter нет ничего, что могло бы IOException , поскольку вы никогда его не отменяли, поэтому он не будет создавать секцию throws . Когда геттер переопределяется, компилятор не имеет возможности узнать, может ли код, который вы предоставили, бросить, поэтому он подчиняется аннотации и всегда выводит часть throws .

ОБНОВИТЬ

Кажется, что создается правильный байт-код:

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

Познакомившись с этим, я не вижу причин для @get:Throws(IOException::class) не работать в этом случае. Вы можете указать проблему на YouTrack для Kotlin и посмотреть, что члены команды должны сказать об этом.