gpt4 book ai didi

Java记录构造函数通过反射不可见

转载 作者:行者123 更新时间:2023-12-03 11:17:38 24 4
gpt4 key购买 nike

我正在使用 Java 15 的新记录功能,以及它如何与反射交互。我遇到了一些奇怪的行为,有时我可以通过反射访问记录的构造函数,有时则不能。例如,给定以下 Java 文件:Recording.java :

public class Recording {
public static void main(String[] args) {
System.out.println("Constructors: " + MainRecord.class.getConstructors().length);
System.out.println("Methods: " + MainRecord.class.getDeclaredMethods().length);
}

record MainRecord(int i, String s) {}
}
其行为如下:
❯ javac --enable-preview --release 15 Recording.java
Note: Recording.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
❯ java --enable-preview Recording
Constructors: 0
Methods: 5
换句话说,对 getConstructors() 的调用没有找到任何构造函数(而对 getDeclaredMethods() 的调用确实找到了方法)。我不明白为什么不,因为构造函数确实存在:
❯ javap Recording\$MainRecord
Compiled from "Recording.java"
final class Recording$MainRecord extends java.lang.Record {
Recording$MainRecord(int, java.lang.String);
public final java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public int i();
public java.lang.String s();
}
(将记录放在单独的 Java 文件中会得到相同的结果。)
但是,如果我从 JShell 做同样的事情:
❯ jshell --enable-preview
| Welcome to JShell -- Version 15
| For an introduction type: /help intro

jshell> record JShellRecord(int i, String s) {}
| created record JShellRecord

jshell> JShellRecord.class.getConstructors().length
$2 ==> 1
所以,现在它 找到构造函数。
这是我正在使用的 Java 版本:
❯ java -version
openjdk version "15" 2020-09-15
OpenJDK Runtime Environment AdoptOpenJDK (build 15+36)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 15+36, mixed mode, sharing)
从 Java 14 编译和运行相同的程序确实有效:
❯ java -version
openjdk version "14.0.2" 2020-07-14
OpenJDK Runtime Environment AdoptOpenJDK (build 14.0.2+12)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 14.0.2+12, mixed mode, sharing)
❯ javac --enable-preview --release 14 Recording.java
Note: Recording.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
❯ java --enable-preview Recording
Constructors: 1
Methods: 5
我知道在 Java 15 中,与 Java 14 相比,对记录的反射设置了许多限制,但是如果我阅读了 JEP正确,那些只适用于修改。查找(并可能调用)构造函数似乎并不适用。
谁能告诉我这里发生了什么?我需要做什么才能通过反射在 Java 15 中查看记录的构造函数?

最佳答案

getConstructors()返回 public仅构造函数。使用 getDeclaredConstructors()获取所有构造函数。
您的声明 record MainRecord(int i, String s) {}缺少 public修饰符,所以它创建了一个非 public类和非 public构造函数。见 JLS15-preview, §8.10.4

The implicitly declared canonical constructor has the same access modifier as the record class R, unless the record class lacks an access modifier, in which case the canonical constructor has package access


这确实与 JDK 14 预览版不同。开头 the JDK 15 preview document说:

The changes are the same as those in the first preview of Records in Java SE 14, except for the following:

  • 8.10.4 Removed requirement that canonical constructor must be public. Any access modifier must provide at least as much access as the record class. If a canonical constructor is implicitly declared, then its access modifier is the same as the record class.

看起来,在 JShell 中创建的顶级类是隐式 public .
> jdk-15\bin\jshell --enable-preview
| Welcome to JShell -- Version 15
| For an introduction type: /help intro

jshell> record JShellRecord(int i, String s) {}
| created record JShellRecord

jshell> JShellRecord.class.getConstructors()[0]
$2 ==> public JShellRecord(int,java.lang.String)

jshell> java.lang.reflect.Modifier.isPublic(JShellRecord.class.getModifiers())
$3 ==> true

jshell>

关于Java记录构造函数通过反射不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63993967/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com