构造函数是否生成了默认构造函数?

Lii*_*Lii 15 java reflection

有没有办法通过反射找出构造函数是否是编译器生成的默认构造函数?或者还有其他方式吗?

令人惊讶的是,该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 []
    }
}
Run Code Online (Sandbox Code Playgroud)

这个问题问同样的事情,但是对于C#:使用C#中的反射检测编译器生成的默认构造函数

Jac*_*far 8

不,编译器生成它们:

我创建了文件A.java:

public class A{
public String t(){return "";}
}
Run Code Online (Sandbox Code Playgroud)

然后:

javac A.java
Run Code Online (Sandbox Code Playgroud)

并运行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       
}
Run Code Online (Sandbox Code Playgroud)

如果我添加构造函数:

public A(){}
Run Code Online (Sandbox Code Playgroud)

结果是:

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       
}
Run Code Online (Sandbox Code Playgroud)

它是完全相同的.我正在使用带有64位OpenJDK的Java 7,但我敢打赌它与所有版本相同.

编辑:实际上,单独的相同字节码并不能保证信息不作为元数据出现.使用十六进制编辑器和该程序可以看到有两个字节不同,并且对应于行号(用于打印堆栈跟踪),因此在这种情况下不存在信息.


cyo*_*yon 5

不,字节码中没有元数据可以让您区分编译器生成的默认构造函数和非生成的默认构造函数.

在大多数情况下,编译器生成的构造函数和方法在生成的字节码中标记有ACC_SYNTHETIC标志或Synthetic属性.但是,根据Java语言规范中的 13.1项目7 和来自jvm-spec的 4.7.8 ,有一些值得注意的例外情况.

以下是JLS的相关内容:

Java编译器引入的任何在源代码中没有相应构造的构造必须标记为合成,除了默认构造函数,类初始化方法以及Enum类的values和valueOf方法

据我所知,javap没有显示ACC_SYNTHETIC标志,但isSynthetic如果设置了,你将能够阅读它.