Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @当目标是属性时,抛出无效_Java_Annotations_Jvm_Kotlin_Throws - Fatal编程技术网

Java @当目标是属性时,抛出无效

Java @当目标是属性时,抛出无效,java,annotations,jvm,kotlin,throws,Java,Annotations,Jvm,Kotlin,Throws,在查看时,我注意到将@Throws应用于get或set使用站点没有效果 此外,@Throws的唯一有效目标是AnnotationTarget.FUNCTION,AnnotationTarget.PROPERTY\u GETTER,AnnotationTarget.PROPERTY\u SETTER和AnnotationTarget.CONSTRUCTOR 其他注释,如JPA注释和不推荐的工作正常,并正确应用于该方法 这是奇怪的行为 为了演示,我用Java创建了一个简单的抽象类,包含一个构造函数、

在查看时,我注意到将
@Throws
应用于
get
set
使用站点没有效果

此外,
@Throws
的唯一有效目标是
AnnotationTarget.FUNCTION
AnnotationTarget.PROPERTY\u GETTER
AnnotationTarget.PROPERTY\u SETTER
AnnotationTarget.CONSTRUCTOR

其他注释,如JPA注释和
不推荐的
工作正常,并正确应用于该方法

这是奇怪的行为

为了演示,我用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
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"
生成带有签名的方法
公共最终字符串getString()抛出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")))));
}
尽管抛出了一个
FileNotFoundException

此外,这对于抽象方法来说也不重要,因为它们不能有实现,而且仍然可以有
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()

}
如果我按照建议执行并添加一个具体实现:

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被重写时,编译器无法知道您提供的代码是否可以抛出,因此它遵循注释,并将始终输出
抛出部分

更新

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

abstract class KotlinAbstractClass {

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

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

尝试实现一个实际引发此异常的getter或setter。如果代码是安全的,则不必重新声明所覆盖内容的
抛出声明。也许Kotlin只是巧妙地使用了它的
@Throws
注释。@tynn我将编辑我的问题。不,我在问题中解决了这两个部分,将
@Throws
直接放在任何getter上,即使它没有抛出,也会添加一个
Throws
子句。将
@get:Throws
放入任何属性(即使它确实抛出)都没有效果。如果我按照你的建议去做,并把
val string:string@Throws(IOException::class)get()=“Foo”
,“编译器足够聪明,可以看到getter中没有任何东西会抛出IOException”,这是不可能的,因为仍然会生成Throws子句。哦,我已经忘记了这种可能性。我同意“使用站点注释”似乎应该有效,我会尽可能做到这一点。谢谢