Является конструктором по умолчанию конструктором?

Есть ли способ выяснить, является ли конструктор компилятором, сгенерированным конструктором по умолчанию или нет? Или есть какой-то другой способ?

Удивительно, что метод 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 []
    }
}

Этот вопрос задает одно и то же, но для С#: Обнаружить созданный компилятором конструктор по умолчанию, используя отражение в С#

Ответы

Ответ 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, но я бы поспорил, что он одинаковый со всеми версиями.

EDIT: на самом деле один и тот же байт-код не гарантирует, что информация отсутствует как метаданные. Используя hex-редактор и эту программу удалось увидеть, что существуют два байта, отличающиеся и соответствующие номерам строк (используемым для печати стеков стека), поэтому в этом случае информация отсутствует.

Ответ 2

Нет, в байт-коде нет метаданных, которые позволят вам отличить созданный по умолчанию конструктор по умолчанию от негенерированного.

В большинстве случаев конструкторы и методы, сгенерированные компилятором, помечены знаком ACC_SYNTHETIC или атрибутом Synthetic в сгенерированном байт-коде. Однако есть несколько примечательных исключений в соответствии с пунктом 13.1 пункта 7 из Java Language Spec и 4.7.8 из jvm-spec

Вот соответствующий бит из JLS:

Любые конструкции, созданные компилятором Java, которые не имеют соответствующей конструкции в исходном коде, должны быть помечены как синтетические, за исключением конструкторов по умолчанию, метода инициализации класса и значений и методов valueOf класса Enum

Насколько я знаю, javap не показывает флаг ACC_SYNTHETIC, но вы могли бы прочитать его через isSynthetic, если он был установлен.