当目标是 属性 时,@Throws 无效
@Throws has no effect when the target is a property
在查看 时,我注意到将 @Throws
应用于 get
或 set
使用站点没有任何效果。
此外,@Throws
的唯一有效目标 是 AnnotationTarget.FUNCTION
、AnnotationTarget.PROPERTY_GETTER
、AnnotationTarget.PROPERTY_SETTER
和 AnnotationTarget.CONSTRUCTOR
.
其他注释,例如 JPA 注释和 Deprecated
工作正常并正确应用于该方法!
这是一种奇怪的行为。
为了演示,我在 Java 中创建了一个简单的抽象 class,具有一个构造函数、一个方法和一个 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 {
}
}
如您所见,每个 method/constructor 都被标记为抛出 IOException
。
但是,当我尝试在 Kotlin 中编写等效的 class,并使用 throws
标记适当的方法进行互操作时,生成的 getString
和 setString
方法没有 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 {
}
}
对我来说,这似乎是因为这些内部注释必须由编译器专门处理,而不是直接应用于方法。
此外,将其应用于非抽象 属性 的 getter:
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
constructor 抛出 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()
这应该会为您提供签名中带有 throws
的正确 Java 版本。我想原因是如果你这样做:
@get:Throws(IOException::class)
val foo: String = "foo"
编译器足够聪明,可以看到 getter 中没有任何内容会抛出 IOException
,因为您从未覆盖它,所以它不会产生 [=13] =] 部分。当 getter 被覆盖时,编译器无法知道您提供的代码是否可以抛出,因此它遵循注释并始终输出 throws
部分。
更新
以下似乎生成了正确的字节码:
abstract class KotlinAbstractClass {
abstract var string: String
@Throws(IOException::class) get
@Throws(IOException::class) set
}
仔细研究后,我认为 @get:Throws(IOException::class)
没有理由不在这种情况下工作。您可以在 YouTrack for Kotlin 上提交问题,看看团队成员对此有何评论。
在查看 @Throws
应用于 get
或 set
使用站点没有任何效果。
此外,@Throws
的唯一有效目标 是 AnnotationTarget.FUNCTION
、AnnotationTarget.PROPERTY_GETTER
、AnnotationTarget.PROPERTY_SETTER
和 AnnotationTarget.CONSTRUCTOR
.
其他注释,例如 JPA 注释和 Deprecated
工作正常并正确应用于该方法!
这是一种奇怪的行为。
为了演示,我在 Java 中创建了一个简单的抽象 class,具有一个构造函数、一个方法和一个 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 {
}
}
如您所见,每个 method/constructor 都被标记为抛出 IOException
。
但是,当我尝试在 Kotlin 中编写等效的 class,并使用 throws
标记适当的方法进行互操作时,生成的 getString
和 setString
方法没有 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 {
}
}
对我来说,这似乎是因为这些内部注释必须由编译器专门处理,而不是直接应用于方法。
此外,将其应用于非抽象 属性 的 getter:
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
constructor 抛出 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()
这应该会为您提供签名中带有 throws
的正确 Java 版本。我想原因是如果你这样做:
@get:Throws(IOException::class)
val foo: String = "foo"
编译器足够聪明,可以看到 getter 中没有任何内容会抛出 IOException
,因为您从未覆盖它,所以它不会产生 [=13] =] 部分。当 getter 被覆盖时,编译器无法知道您提供的代码是否可以抛出,因此它遵循注释并始终输出 throws
部分。
更新
以下似乎生成了正确的字节码:
abstract class KotlinAbstractClass {
abstract var string: String
@Throws(IOException::class) get
@Throws(IOException::class) set
}
仔细研究后,我认为 @get:Throws(IOException::class)
没有理由不在这种情况下工作。您可以在 YouTrack for Kotlin 上提交问题,看看团队成员对此有何评论。