Почему вы не можете наследовать от класса, конструктор которого является закрытым?

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

 CodeBlue21 мая 2013 г., 09:00
@HovercraftFullOfEels, см. Питер Лориответ.

Ответы на вопрос(5)

Если конструктор класса является закрытым, то дочерний класс не может вызвать супер конструктор. Следовательно наследство потерпит неудачу.

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

Больше информации:JLS 8.8.10. Предотвращение создания класса

Относительно Брайана Роучакомментарии:

Вызов [в конструктор родительского класса] неявен, только если вы нене делать это явно, и у родителя есть открытый или защищенный конструктор без аргументов (или hasn 'т определил любой, и в этом случаепо умолчанию нет аргументов). Это'требуется, потому что ... этокак работает язык Дети [классы] должны называть [своих] родителейконструктор

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

public Object() {
}

Примечание по ссылке JLS:

Это ошибка времени компиляции, если конструктор по умолчанию неявно объявленно у суперкласса нет доступного конструктора (§6.6), который не принимает аргументов и не имеет предложения throws.

 cogsmos21 мая 2013 г., 05:29
В каждом конструкторе есть неявный вызов super (), если вы сами его не указали.
 Luiggi Mendoza21 мая 2013 г., 05:42
@CodeBlue ответ обновлен.
 CodeBlue21 мая 2013 г., 05:32
Я имею в виду призыв к тому, чтобы супер был неявным. Почему нужно называть супер в первую очередь? Это просто так, как они это спроектировали, или для этого есть все основания?
 Brian Roach21 мая 2013 г., 05:34
Звонок является неявным, если вы нене делать это явно, и у родителя есть открытый или защищенный конструктор без аргументов (или hasn 'т определил любой, и в этом случаепо умолчанию общедоступный без аргументов). Это'требуется, потому что ... этокак работает язык. Дети должны позвонить родителюконструктор
 Brian Roach21 мая 2013 г., 05:28
Если родительский класс объявил приватный конструктор, тогдаНичего скрытого в этом нет. Это потребовало бы явного вызова в дочернем элементе, но поскольку конструктор является закрытым, вы можетет.
 Luiggi Mendoza21 мая 2013 г., 05:44
@BrianRoach спасибо за вашу помощь.
 CodeBlue21 мая 2013 г., 05:22
И почему это необходимое условие, даже если оно неявное?

Если у вас есть подкласс, у вас есть 2 возможности для конструкторов дочернего класса (подкласса): 1. Конструктор по умолчанию (без конструктора аргументов): в этом случае конструктор по умолчанию автоматически попытается вызвать конструктор родительского класса: это не удастся, так как конструктор родительского класса это личное. 2. Параметризованный конструктор: когда вы пытаетесь создать объект для дочернего класса, у которого есть параметризованный конструктор, вам нужно обязательно вызвать конструктор родительского класса из конструктора дочернего класса, передавая p, arameters или не передавая параметры: это также не удастся, так как parent Конструктор является частным.

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

Решение Вопроса

Ява неt предотвратить подклассы класса с частными конструкторами.

public class Main {
    static class A {
        private A() {
            System.out.println("Subclassed A in "+getClass().getName());
        }
    }

    static class B extends A {
        public B() {

        }
    }

    public static void main(String... ignored) {
        new B();
    }
}

печать

Subclassed A in Main$B

Он предотвращает подклассы, которые не могут получить доступ к конструкторам своего суперкласса. Это означает, что закрытый конструктор нельзя использовать в другом файле класса, а локальный конструктор пакета нельзя использовать в другом пакете.

В этой ситуации единственный вариант у вас есть делегирование. Вам нужно вызвать фабричный метод для создания экземплярасупер" класс и завернуть его.

 Grateful27 мая 2015 г., 08:49
@PeterLawrey Спасибо
 Peter Lawrey27 мая 2015 г., 06:37
@ Благодарственное замечание, это относится и к полям, методам и даже к частным гнездам.
 Grateful27 мая 2015 г., 02:43
@PeterLawrey Хорошо, я думаю, простое объяснение для меня заключается в том, что Java позволяет получить доступ к закрытым конструкторам других вложенных классов.
 Peter Lawrey26 мая 2015 г., 08:43
@ Благодарен тому факту, что код находится в том же внешнем классе, что делает все это для доступа к закрытым членам. JVM не делаетЭто невозможно, поэтому компилятор создает методы доступа, такие какaccess $010
 Grateful26 мая 2015 г., 10:13
@PeterLawrey Извините, я нене понимаю последний комментарий. У вас будет время, чтобы уточнить?
 Peter Lawrey26 мая 2015 г., 23:36
@Grateful Хотя Java разрешает доступ к закрытым членам других классов, JVM нет. Компилятор создает методы доступа, которые позволяют коду Java обращаться к полям / методам / конструкторам, которые вы не хотитеиначе не сможет получить доступ.
 Tom Hawtin - tackline08 янв. 2019 г., 23:45
@PeterLawrey Ну, да, если ты примешь меры безопасности ... Что?Интересно, IMO, это то, что вы можете сделать, не нанеся вреда окружающей среде.
 Peter Lawrey26 мая 2015 г., 06:14
@ Благодарный B может получить доступ к членам A, поскольку они находятся в одном внешнем классе. Это верно и для полей и методов. Однако, если A и B не находятся в одном и том же файле, а A имеет частные или даже упакованные локальные конструкторы, и B не сможетт доступ к ним, в этом случае B не может подкласс A.
 Peter Lawrey16 окт. 2014 г., 08:49
@jaxox для jvm, вложенные классы не являются чем-то особенным. Они похожи на любой другой класс с более метаинформацией. Таким образом, вы можете создать класс, который был определен как вложенный, как любой другой. Кстати, анонимные классы в статических методах также являются статическими вложенными классами.
 Peter Lawrey08 янв. 2019 г., 23:52
@ TomHawtin-tackline, вы можете использовать Unsafe, чтобы скопировать указатель класса в заголовке из одного объекта в другой, чтобы "бросать" один тип к другому. ;)
 Jaxox15 окт. 2014 г., 07:36
что-то неправильно? создать вложенный статический класс? как это работает?
 Peter Lawrey08 янв. 2019 г., 22:46
@ TomHawtin-tacklineUnsafe.allocateInstance(Class) создает экземпляр класса без вызова конструктора. Он может создавать новые значения Enum, но не экземплярыClass ;)
 Grateful26 мая 2015 г., 07:36
@PeterLawrey That 'хорошо. Мне интересно узнать больше о том, как класс B решает проблему приватности A (). Только потому, что оба класса вложены в один и тот же внешний класс ... действительно ли он квалифицирует один класс для доступа к закрытому конструктору другого? Или он вызывает конструктор по умолчанию внешнего класса и полностью игнорирует конструктор класса А?
 Tom Hawtin - tackline08 янв. 2019 г., 21:16
Точка дальнейшей педантичности: Вы можете в байтовом коде создать класс без конструктора. Вы даже можете создать экземпляр, если базовый класс сериализуем. / Возможно, стоит отметить, что вы никогда не сможете переопределить закрытый метод из-за JDK 1.00.
 Grateful26 мая 2015 г., 04:56
@PeterLawrey Я понимаю, что вы говорите, но я все еще немного сбит с толку. Didn»Вы говорите, что Java неt позволяют подклассам не иметь доступа к соответствующим конструкторам суперкласса. Ну, в вашем примере, класс B нене имеет доступа кконструктор Так как это разрешено?

Да, добавив что-то в ЛуиджиОтвет s: эта особенность java используется при создании классов Singleton, которая позволяет создавать только один экземпляр этого класса.

 Sanjaya Liyanage21 мая 2013 г., 06:04
@ Джош, спасибо Джош.
 Sanjaya Liyanage21 мая 2013 г., 05:32
@ Брайан, не могли бы вы сказать мне, как сделать это правильно, не делая конструктор закрытым?
 Brian Roach21 мая 2013 г., 05:36
Джош Блох, 'Эффективное Java, второе издание » - использоватьenum, Увидеть:stackoverflow.com/questions/5759596/... , Если вы некупи эту книгу. Это'Это необходимо прочитать для тех, кто серьезно относится к Java
 Brian Roach21 мая 2013 г., 05:30
Нет, если тысоздать синглтон правильно.

Ваш ответ на вопрос