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

Как класс Java не имеет конструктора no-arg?

В учебном сайте Oracle Java есть этот параграф, который меня путает:

Все классы имеют по крайней мере один конструктор. Если класс не явно объявлять любые, Java компилятор автоматически предоставляет конструктор без аргументов, называемый конструктор по умолчанию. Это значение по умолчанию конструктор вызывает родительский класс класса конструктор без аргументов или объект Object конструктор, если класс не имеет другого Родитель. Если у родителя нет конструктор (объект имеет один), компилятор отклонит программу.

Если все объекты прямо или косвенно наследуются от Object, как можно вызвать отказ от компилятора? Это связано с тем, что конструктор является закрытым?

4b9b3361

Ответ 1

Если все объекты прямо или косвенно наследуются от Object, как можно вызвать отказ от компилятора?

Я думаю, что основой вашего недоразумения является то, что вы думаете, что конструкторы наследуются. На самом деле, конструкторы НЕ наследуются на Java. Поэтому рассмотрим следующий пример:

public class A {
    public A(int i) { super(); ... }
}

public class B extends A {
    public B() { super(); ... }
}

Класс A:

  • не наследует никаких конструкторов из Object,
  • явно не объявляет конструктор no-args (т.е. public A() {...}) и
  • не имеет конструктора по умолчанию (поскольку он объявляет другой конструктор).

Следовательно, он имеет один и только один конструктор: public A(int).

Вызов super() в классе B пытается использовать несуществующий конструктор no-args в A и дает ошибку компиляции. Чтобы исправить это, вам нужно либо изменить конструктор B, чтобы использовать конструктор A(int), либо объявить явный конструктор no-args в A.

(Кстати, конструктору явно не нужно явно вызывать конструктор суперкласса... как я это делал, но многие считают, что хороший стиль включает явный вызов. Если вы его не заметите, компилятор Java вставляет неявный вызов суперклассам no-args constructor... и это приводит к ошибке компиляции, если конструктор no-args не существует или не отображается подклассу.)

Связано ли это с закрытым конструктором?

Не напрямую. Однако объявление частного объекта-конструктора предотвратит вызов этого конструктора из дочернего класса.

Ответ 2

Главное, чтобы понять, что конструктор no-arg будет только автоматически генерироваться, если класс еще не имеет конструктора.

Таким образом, легко создать класс, у которого нет конструктора no-arg.

Ответ 3

Самый простой способ подумать об этой проблеме:

  • Конструктор non-args предоставляется как конструктор по умолчанию Java для любого создаваемого вами класса.

  • В тот момент, когда вы создаете настраиваемый конструктор с аргументами, Java говорит: " эй, этот класс имеет настраиваемый конструктор, поэтому я не собираюсь создавать/поставлять конструктор по умолчанию, отличный от args!"

  • В результате теперь ваш класс НЕ имеет конструктор по умолчанию, отличный от args.

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

Ответ 4

Если у вас есть подкласс класса

class A 
{
    A(int i) {..}
}

class B extends A 
{
}

Здесь конструктор по умолчанию, вставленный в B, попытается вызвать конструктор без аргументов (который не существует), поскольку он имеет только конструктор, принимающий один аргумент

Ответ 5

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

Ответ 6

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

Объявление частного конструктора предотвращает автоматическое создание конструктора по умолчанию.

EDIT:

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

Ответ 7

Это означает, что если вы наследуете строку класса (es), которая делает конструктор no-arg по умолчанию закрытым (или его не существует, например), ваши подклассы должны объявлять конструктор в соответствии с его родительский альтернативный конструктор.

Например, следующее объявление панели запрещается:

public class Foo {
  private Foo() {  } // or this doesn't even exist
  public Foo(int i) {
  }
}
public class Bar extends Foo {
}

Ответ 8

Позвольте мне добавить во все вышеупомянутый еще один интересный случай, когда конструктор default/no-arg недостижим в том смысле, что, если он явно не объявлен, компилятор не может его принять, и все же он не имеет никакого отношения к подклассу. Это относится к классу с полем final, который ожидает, что конструктор инициализирует его. Например:

class Foo extends Object {
    private final Object o;

    public Foo(Object o){
       this.o = o;
    }
}

Здесь легко видеть, что для создания Foo-объекта требуется инициализация конечного поля o, поэтому любое обращение Foo() - напрямую или нет - обречено на провал... Позвольте мне подчеркнуть, что конструктор no-arg в суперклассе (Object) существует и является общедоступным, но это наличие конечного поля (o), которое дезактивирует его в Foo.