Подтвердить что ты не робот

Почему компиляция класса, содержащего статические вложенные классы, создает новый .class файл с именем "EnclosingClass $1"?

В приведенном ниже коде:

 class EnclosingClass
 { 
     public static class BiNode extends Sub.IBiLink { }
     private static class Sub
     {
         private static class IBiLink
         {  
         } 
     }
}

При компиляции вместе с другими .class файлами я также вижу файл с именем "EnclosingClass $1.class". Почему это было автоматически создано? Что происходит?

4b9b3361

Ответ 1

Сначала взгляните на таблицу модификатора доступа к классам и свойствам из спецификаций JVM.

enter image description here

Обратите внимание на флаг ACC_SYNTHETIC, интерпретация которого указывает, что он отсутствует в исходном коде (в более простых словах он будет добавлен, когда класс будет сгенерирован компилятором).


Посмотрим на байт-код EnclosingClass$1.class (обратите внимание, что я вложу только ту часть, которая имеет значение).

javap -v EnclosingClass$1.class

выведите следующий результат

Classfile /C:/Users/jfrancoiss/Desktop/Nouveau dossier/EnclosingClass$1.class
  Last modified 2015-03-31; size 190 bytes
  MD5 checksum 5875440f1e7f5ea9a519d02fbec6dc8f
  Compiled from "EnclosingClass.java"
class EnclosingClass$1
  minor version: 0
  major version: 52
  flags: ACC_SUPER, ACC_SYNTHETIC    

Обратите внимание, что флаги доступа класса содержат ACC_SYNTHETIC.

Флаг ACC_SYNTHETIC указывает, что этот класс или интерфейс был созданный компилятором и не отображающийся в исходном коде.

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

javac -XD-printflat EnclosingClass.java

который произведет

/*synthetic*/ class EnclosingClass$1 {
}

Отлично, но зачем генерировать синтетический класс?

Учебник по отражению Java поможет нам понять это. Взгляните на комментарии в SyntheticConstructor class

public class SyntheticConstructor {
    private SyntheticConstructor() {}
    class Inner {
    // Compiler will generate a synthetic constructor since
    // SyntheticConstructor() is private.
    Inner() { new SyntheticConstructor(); }
    }
}

Итак, согласно комментарию, синтетический класс EnclosingClass$1.class был создан, потому что IBiLink был закрытым.

Еще раз, java reflection tutorial укажите в этот момент

Так как внутренний конструктор классов ссылается на частный конструктор охватывающего класса компилятор должен сгенерировать пакет-частный конструктор.

В нашем случае мы не видим явно никакого вызова конструктора, но мы имеем эту строку

public static class BiNode extends Sub.IBiLink { }

Попробуйте выполнить компиляцию этого кода и посмотреть, что произойдет

class EnclosingClass
 { 
     //public static class BiNode extends Sub.IBiLink { }
     private static class Sub
     {
         private static class IBiLink
         {  
         } 
     }
}

Нет EnclosingClass$1.class.


Подробнее при отладке

Измените

private static class IBiLink

к

protected static class IBiLink

обратите внимание, что при компиляции EnclosingClass$1.class не создается.

Почему защита класса не создала синтетический класс?

Просто потому, что при защите класса вы неявно получаете доступ к каждому из суперклассов.


Почему компилятор eclipse не генерирует синтетический класс?

Eclipse использует встроенный компилятор, который вы можете настроить его уровень серьезности.

По умолчанию доступ к незанятому члену закрывающего типа устанавливается как игнорируемое, как вы можете видеть на этом изображении.

enter image description here

Измените его, например, на предупреждение, и вы получите следующее сообщение.

enter image description here

которые позволяют мне полагать, что затмение, altought не создает другого класса, будет эмулировать его для имитации синтетического элемента.