构造函数生成的构造函数是默认构造函数吗?

2022-09-03 15:05:40

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

令人惊讶的是,该方法没有提供此信息,因此无法使用。并且没有注释存在。isSyntheticGenerated

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#中的反射检测编译器生成的默认构造函数


答案 1

否,编译器会生成它们:

我创建了文件: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,但我敢打赌它对所有版本都是一样的。

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


答案 2

不可以,字节码中没有元数据允许您将编译器生成的默认构造函数与非生成的构造函数区分开来。

在大多数情况下,编译器生成的构造函数和方法在生成的字节码中使用标志或属性进行标记。但是,根据 Java 语言规范中的 13.1 项 7 和 jvm 规范中的 4.7.8,有一些值得注意的例外。ACC_SYNTHETICSynthetic

以下是JLS的相关部分:

Java 编译器引入的任何在源代码中没有相应构造的构造都必须标记为综合构造,但缺省构造函数、类初始化方法以及 Enum 类的值和 valueOf 方法除外

据我所知,不显示标志,但如果设置了它,您将能够通读它。javapACC_SYNTHETICisSynthetic