В Java сколько конструкторов мы можем создать в одном классе? - программирование
Подтвердить что ты не робот

В Java сколько конструкторов мы можем создать в одном классе?

В Java, сколько конструкторов мы можем создать в одном классе.

4b9b3361

Ответ 1

Строго говоря, формат файла классов JVM ограничивает число методов (включая все конструкторы) для класса не более 65536. И, по словам Тома Хоутина, эффективный предел составляет 65527. Каждая сигнатура метода занимает слот в пуле констант. Поскольку некоторые из 65535 записей пула (неизбежно) используются другими вещами, правильно сформированный файл класса не может использовать все возможные идентификаторы методов/конструкторов.

Ссылка - JVMS 4.1 Структура ClassFile

Однако, если вы пишете разумный код Java обычным способом, вы не столкнетесь с этим ограничением.

Сколько у вас должно быть? Это зависит от вариантов использования классов. Часто бывает полезно иметь несколько перегрузок "удобного" конструктора, причем все они используют this(...) для цепочки с "главным" конструктором. Тем не менее, вы можете пойти поверх.

Если вы обнаружите, что пишете чрезмерное (субъективное!) Число конструкторов, вам, возможно, следует поискать альтернативы, такие как шаблон Builder.

Ответ 2

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

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

Конструкторы компилируются в специальные методы (с именем <init>), поэтому в файле класса они совместно используют таблицу с обычными методами, которая ограничена 65535 записями. Мы можем максимизировать это, не объявляя какие-либо обычные методы. Кроме того, поскольку каждый конструктор должен иметь отдельную сигнатуру, каждый конструктор нуждается в собственной строке сигнатуры типа в пуле констант, который сам по себе ограничен 65534 записями.

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

Таким образом, минимальные постоянные записи пула, необходимые

  1. имя суперкласса (измененная запись UTF8)
  2. суперкласс (тип Class, ссылаясь на 1.)
  3. имя этого класса (измененная запись UTF8)
  4. этот класс (тип Class, ссылаясь на 3.)
  5. Конструкторы "Метод" имя <init> (измененная запись UTF8)
  6. запись name & type, ссылающаяся на 5. и подпись супер-конструктора (может использоваться совместно с одной из наших подписей конструкторов)
  7. запись метода, ссылающаяся на 2. и 6. (для вызова супер-конструктора)
  8. Code имени атрибута (измененная запись UTF8)

Учитывая эти обязательные записи и ограничение в 65534 записи (размер плюс один хранится в виде двухбайтового числа без знака), мы получаем ограничение на размер файла класса 65526 конструкторов, и действительно, я могу сгенерировать действительный файл класса, используя библиотеку ASM с этим номером. конструкторов и не более.

На самом деле, вы могли бы получить больше, если бы назвали свой класс java.lang.Object, так как в этом особом случае нет суперкласса для объявления и нет супер-конструктора для вызова. Решите сами, какой фактический лимит вы хотите назвать максимальным номером…

Как уже было сказано, есть третье ограничение - реализация компилятора. При использовании Java-компилятора вы должны убедиться, что он не генерирует отладочную информацию (в случае javac используйте -g:none) и никаких других необязательных атрибутов, которые могут занимать постоянные записи пула. Но с javac из JDK11, производительность будет значительно снижаться при запуске определения многих конструкторов. Я получил следующие времена компиляции:

 1000 constructors:   1 second
 2000 constructors:   2 seconds
 5000 constructors:  10 seconds
10000 constructors:   1 minute
15000 constructors:   2 minutes
20000 constructors:   4 minutes
30000 constructors:  10 minutes
40000 constructors:  20 minutes
50000 constructors:  between 25 minutes and ½ hour
65526 constructors:  between 45 minutes and 1 hour

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

Компилятор Eclipse, похоже, лучше справляется с такими исходными файлами, но, тем не менее, максимальное количество конструкторов делало IDE практически непригодной для использования. С отключенными символами отладки и немного терпения, мне удалось собрать класс с 65526 конструкторами с Eclipse. Объявление 65528 конструкторов привело к сообщению об ошибке, касающемуся слишком большого числа записей константного пула, а объявление 65527 конструкторов выявило ошибку в Eclipse, в результате которой был поврежден файл класса, объявляющий нулевые записи пула констант (как было сказано ранее, число сохраняется как число плюс один, поэтому поставщики компиляторов Следует иметь в виду, что предел не 65535, а 65534).

Ответ 3

Перегрузка конструктора конструктора Java (когда класс java содержит несколько конструкторов, он вызывается, когда конструктор перегружен). Класс может иметь несколько конструкторов, если их подпись (параметр) не является одинаковой. Таким образом, вы можете определить многие конструкторы по мере необходимости. Нет предела. Вот пример: -

class Demo {
    private String name;
    private String city;
    private Double salary;

    public Demo() {
    }

    public Demo(String name) {
        this.name = name;
    }
    public Demo(Double salary) {
        this.city = city;
    }
    public Demo(String name,String city) {
        this.name = name;
        this.city = city;
    }
}

Ответ 4

Вы можете иметь 65535 конструкторов в классе (согласно документации Oracle). Но ВАЖНО имейте это в виду. Мы достигаем этого только путем ПЕРЕГРУЗКИ КОНСТРУКТОРА (https://beginnersbook.com/2013/05/constructor-overloading/). Вы можете создать много конструкторов, но с разными подписями.

Ответ 5

У вас может быть как можно больше конструкторов в классе. JAVA не накладывает никаких ограничений на количество конструкторов, которые может иметь класс. Просто эти конструкторы могут быть либо параметризированы, либо по умолчанию..

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

параметризованный конструктор. Параметрированный конструктор имеет один или несколько параметров и используется для инициализации каждого объекта разными данными.

Ответ 6

ТЛ; др

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

  • 65526 для класса с именем по вашему выбору.
  • 65527 для класса с именем Code (по одному на загрузчик классов).
  • 65530 для класса с именем java.lang.Object (по одному на ВМ).

Детали

Вопрос был закрыт до того, как я опубликовал свой ответ. Так что здесь биты дополнительные к тому, что @Holger уже рассмотрел.

Соответствующий раздел спецификации JVM - 4.1. Структура ClassFile в издании Java SE 11.

u2             constant_pool_count;
cp_info        constant_pool[constant_pool_count-1];

Обратите внимание на -1. Записи пронумерованы от 1. 0 используется для обозначения:

  • класс без суперкласса (интересно!)
  • формальный параметр без имени
  • модуль без информации о версии
  • модульная зависимость без информации о версии

Если класс называется Code эта строковая константа будет дедуплирована с требуемым именем атрибута Code (см. Ответ @Holger). Вам понадобится очень старая версия javac если вы хотите получить к ней доступ из пакета по умолчанию.

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

javac работает все медленнее (O (n ^ 2) ish?) является хорошим примером постепенной деградации. :)

Перемена

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

public class Min1 {
   public Min1() {
   }
   /* Followed by (int a), (byte a), (int a, byte b), etc. */
}

Компиляция без отладочной информации (люди все еще случайно распространяют файлы классов с отладочной информацией?).

javac -g:none Min1.java

Список содержимого со старым javap.

javap -verbose Min1

Должен дать вам что-то вроде

Classfile /Users/tackline/code/scratch/minimal_class/Min1.class
  Last modified Dec 5, 2018; size 119 bytes
  MD5 checksum c1a6b7c31c286165e01cc4ff240e7718
public class Min1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#7          // java/lang/Object."<init>":()V
   #2 = Class              #8             // Min1
   #3 = Class              #9             // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = NameAndType        #4:#5          // "<init>":()V
   #8 = Utf8               Min1
   #9 = Utf8               java/lang/Object
{
  public Min1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
}

Ответ 7

5 типов

Конструкторы можно разделить на 5 типов: конструктор по умолчанию. Параметризированный конструктор. Копировать конструктор. Статический конструктор.

Но в java мы имеем в основном только 2 типа конструкторов. 1. По умолчанию 2. Параметризация

Мы также можем перегружать конструкторы в соответствии с нашей потребностью

Более одного конструктора с различной сигнатурой в классе называется перегрузкой конструктора. Подпись конструктора включает:

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

МЫ МОЖЕМ СОЗДАТЬ БЕСКОНЕЧНОЕ КОЛИЧЕСТВО КОНСТРУКТОРА В КЛАССЕ

Ответ 9

Вы можете создать 65535 конструкторов в одном классе

Дополнительная информация: Oracle Docs

Ответ 10

Нет ограничений на количество конструкторов, которые может иметь класс.