当目标是属性时,@Throws 不起作用

2024-05-11

在看的同时这个问题 https://stackoverflow.com/q/47737288/7366707,我注意到申请@Throws to a get or setuse-site 没有影响。

此外,唯一有效的目标 for @Throws are AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, and 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对于互操作,生成的getString and setString方法没有throws clause.

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"

does生成带有签名的方法public final String getString() throws IOException!

也许这个案子处理得不好?

这是一个错误吗?


注意:这与该方法是否实际抛出此异常没有任何关系。

If I do:

@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构造函数 https://docs.oracle.com/javase/7/docs/api/java/io/FileReader.html#FileReader(java.io.File)抛出一个FileNotFoundException.

此外,无论如何,这对于抽象方法来说并不重要,因为它们不能有实现,但仍然可以有一个throws clause.

如果我这样做@tynn https://stackoverflow.com/users/3385212/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部分。当 getter 被重写时,编译器无法知道您提供的代码是否会抛出异常,因此它遵循注释并始终输出throws part.

UPDATE

以下似乎生成了正确的字节码:

abstract class KotlinAbstractClass {

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

仔细观察后,我发现没有任何理由@get:Throws(IOException::class)在这种情况下不工作。您可以在 YouTrack for Kotlin 上提交问题,看看团队成员对此有何评论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当目标是属性时,@Throws 不起作用 的相关文章

随机推荐