Есть ли накладные расходы на производительность для частного внутреннего класса в Java?

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

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

Но как насчет видимости самого класса? Есть ли накладные расходы для

 private static class A {
      A(){}
 }

против

 static class A {
      A(){}
 }

Обратите внимание, что конструктор защищен пакетом в обоих случаях или делает приватное изменение класса таким?

Ответ 1

Вы пытались скомпилировать его и сравнивать байтовый код? Вот мои результаты. Для:

public class Example {
  public static void main(String[] args) {
    System.out.println("Hello world!");
  }
  private static class A {
    A(){}
  }
}

Вышеприведенные файлы *.class:

-rw-r--r--    1 michaelsafyan  staff   238 Feb 10 00:11 Example$A.class
-rw-r--r--    1 michaelsafyan  staff   474 Feb 10 00:11 Example.class

Теперь, если я перемещаю файлы классов, удаляю модификатор private и перекомпилирую, я получаю:

 -rw-r--r--    1 michaelsafyan  staff   238 Feb 10 00:15 Example$A.class
 -rw-r--r--    1 michaelsafyan  staff   474 Feb 10 00:15 Example.class

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

Короче говоря, ваши модификаторы доступа не будут влиять на размер сгенерированного байтового кода (он также не должен иметь никакого влияния на производительность). Вы должны использовать модификатор доступа, который имеет наибольший смысл.

Я также должен добавить, что есть небольшая разница, если вы измените внутренний класс на объявленный static на не объявляемый static, поскольку это подразумевает дополнительное поле, ссылающееся на внешний класс. Это займет немного больше памяти, чем если бы вы объявили внутренний класс static, но вы были бы безумны для оптимизации для этого (используйте static там, где это имеет смысл, и где вам нужно, чтобы он был нестатичным, он нестационарен, но не свертывает ваш дизайн, просто чтобы сохранить указатель на память здесь или там).

Ответ 2

Не должно быть разницы в производительности между частным внутренним классом и неличным внутренним классом.

Не должно быть разницы в производительности между статическим внутренним классом (private или нет) и внешним классом.

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

Ответ 3

Очень маловероятно, что это когда-либо приведет к значительным замедлениям.

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

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

Это не относится к статическим внутренним классам!

Предоставление всех защищенных полей для предотвращения синтетических методов нецелесообразно. Вы отказываетесь от инкапсуляции, которая является ценной вещью. Каковы ваши проблемы? Размер ваших файлов классов для дополнительного кода?