有没有办法通过反射来确定构造函数是否是编译器生成的默认构造函数?或者还有别的办法吗?
令人惊讶的是,isSynthetic
方法没有给出这些信息,因此无法使用。并且不存在Generated
注释。
public class JavaTest {
public void run() throws Exception {
out.println(JavaTest.class.getConstructors()[0].isSynthetic()); // Prints false
out.println(Arrays.asList(JavaTest.class.getConstructors()[0].getAnnotations())); // Prints []
}
}
这个问题问了同样的问题,但对于C#:使用C#中的反射来检测编译器生成的默认构造函数
否,编译器生成它们:
我创建了文件A.java
:
public class A{
public String t(){return "";}
}
然后:
javac A.java
运行javap -c A
查看内容:
Compiled from "A.java"
public class A {
public A();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.String t();
Code:
0: ldc #2 // String
2: areturn
}
如果我添加构造函数:
public A(){}
结果是:
Compiled from "A.java"
public class A {
public A();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.String t();
Code:
0: ldc #2 // String
2: areturn
}
它是一样的。我使用Java 7和64位OpenJDK,但我敢打赌,所有版本都是一样的。
EDIT:事实上,单独使用相同的字节码并不能保证信息不会作为元数据出现。使用十六进制编辑器和该程序可以看到有两个不同的字节,并且对应于行号(用于打印堆栈跟踪),因此在这种情况下没有信息。
否,字节码中没有允许您区分编译器生成的默认构造函数和非生成构造函数的元数据。
在大多数情况下,编译器生成的构造函数和方法在生成的字节码中用ACC_SYNTHETIC
标志或Synthetic
属性进行标记。然而,根据Java语言规范13.1第7项和jvm规范第4.7.8项,有一些值得注意的例外
以下是JLS的相关位:
Java编译器引入的任何在源代码中没有相应构造的构造都必须标记为合成,,默认构造函数、类初始化方法以及Enum类的值和valueOf方法除外
据我所知,javap
不显示ACC_SYNTHETIC
标志,但如果设置了isSynthetic
,则可以通过它读取。