@Throws no tiene ningún efecto cuando el objective es una propiedad

Al echar un vistazo a esta pregunta , noté que aplicar @Throws a un sitio de uso get o set no tiene ningún efecto.

Además, los únicos destinos válidos para @Throws son AnnotationTarget.FUNCTION , AnnotationTarget.PROPERTY_GETTER , AnnotationTarget.PROPERTY_SETTER y AnnotationTarget.CONSTRUCTOR .

Otras annotations, como las annotations de JPA y el trabajo en Deprecated funcionan bien y se aplican correctamente al método.

Este es un comportamiento extraño.

Para demostrar, creé una class abstracta simple en Java, con un constructor, un método y un método 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 { } } 

Como puede ver, cada método / constructor está marcado como arrojando IOException .

Sin embargo, cuando bash escribir una class equivalente en Kotlin y marcó los methods apropiados con throws para interoperabilidad, los methods getString y setString generados no tienen cláusula 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() } 

El código descomstackdo:

 @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 { } } 

Para mí, parece ser porque estas annotations internas deben ser manejadas especialmente por el comstackdor, en lugar de aplicarse directamente al método.

Además, al aplicarlo al comprador de una propiedad no abstracta:

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

genera un método con la firma public final String getString() throws IOException !

Tal vez este caso no se manejó correctamente?

¿Es esto un error?


Nota: Esto no tiene nada que ver con si el método arroja realmente esta exception.

Si lo hago:

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

El código comstackdo está todavía

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

a pesar de que el constructor FileReader arroja una FileNotFoundException .

Además, esto no debería importar para los methods abstractos de todos modos, ya que no pueden tener una implementación y aún pueden tener una cláusula throws .

Si hago lo que @tynn sugiere y añado una implementación concreta:

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

Todavía obtengo el mismo resultado.

    Creo que @tynn sugiere que hagas lo siguiente:

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

    Esto debería darle la versión de Java adecuada con throws en la firma. Supongo que el razonamiento es que si solo haces esto:

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

    el comstackdor es lo suficientemente inteligente como para ver que no hay nada en el getter que arroje una IOException , ya que nunca la ha anulado, por lo que no producirá la sección throws . Cuando se anula el getter, el comstackdor no tiene manera de saber si el código que ha suministrado puede arrojar, por lo que obedece a la anotación y siempre dará como resultado la parte throws .

    ACTUALIZAR

    Lo siguiente parece generar un bytecode correcto:

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

    Después de echarle un vistazo más de cerca, no veo ninguna razón para que @get:Throws(IOException::class) no funcione en este caso. Puede presentar un problema en YouTrack for Kotlin y ver lo que los miembros del equipo tienen que decir al respecto.