在final variable passed to anonymous class via constructor中,Jon Skeet提到变量通过自动生成的构造函数传递给匿名类实例。在这种情况下,为什么我无法使用反射看到构造函数:
public static void main(String... args) throws InterruptedException {
final int x = 100;
new Thread() {
public void run() {
System.out.println(x);
for (Constructor<?> cons : this.getClass()
.getDeclaredConstructors()) {
StringBuilder str = new StringBuilder();
str.append("constructor : ").append(cons.getName())
.append("(");
for (Class<?> param : cons.getParameterTypes()) {
str.append(param.getSimpleName()).append(", ");
}
if (str.charAt(str.length() - 1) == ' ') {
str.replace(str.length() - 2, str.length(), ")");
} else
str.append(')');
System.out.println(str);
}
}
}.start();
Thread.sleep(2000);
}
输出结果为:
100
constructor : A$1()
答案 0 :(得分:27)
在这种情况下,这是因为100是常数。这会融入你的课堂。
如果您将x
更改为:
final int x = args.length;
...然后你会在输出中看到Test$1(int)
。 (尽管没有明确声明它。是的,捕获更多变量会为构造函数添加参数。)
答案 1 :(得分:16)
以下是您的程序在我的系统上打印出来的内容:
100
constructor : A$1()
所以构造函数在那里。但是,它是无参数的。通过查看反汇编,发生的情况是编译器发现它不需要将x
传递给run()
,因为它的值在编译时是已知的。
如果我更改代码:
public class A {
public static void test(final int x) throws InterruptedException {
new Thread() {
public void run() {
System.out.println(x);
for (Constructor<?> cons : this.getClass()
.getDeclaredConstructors()) {
StringBuilder str = new StringBuilder();
str.append("constructor : ").append(cons.getName())
.append("(");
for (Class<?> param : cons.getParameterTypes()) {
str.append(param.getSimpleName()).append(", ");
}
if (str.charAt(str.length() - 1) == ' ') {
str.replace(str.length() - 2, str.length(), ")");
} else
str.append(')');
System.out.println(str);
}
}
}.start();
Thread.sleep(2000);
}
public static void main(String[] args) throws InterruptedException {
test(100);
}
}
现在生成的构造函数是:
constructor : A$1(int)
唯一的论点是x
的价值。