Как class может иметь свой собственный тип, это не бесконечная recursion?

Скажем, я определяю class, у которого в качестве члена есть переменная того же типа, что и сама.

public class abc { private abc p; } 

Это действительно работает, к моему удивлению.

Почему я думаю, что это не должно: создаем экземпляр abc , он содержит переменную типа abc , которая содержит переменную типа abc , которая содержит переменную типа abc , которая …..

Очевидно, я ошибаюсь, может кто-нибудь просветить меня о том, как?

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

 public class Abc { private Abc p = new Abc(); // have fun! public static void main(String[] args) { new Abc(); } } 

Кстати, если вы не создаете его в classе, а скорее принимаете ссылку на него в методе getter или в параметре конструктора, ваш код будет работать нормально. Так работают некоторые связанные списки.

Разница заключается в проверке времени компиляции и времени выполнения.

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

Во втором случае (время выполнения) вы фактически создадите значение для этой ссылки для ссылки. Здесь вы можете столкнуться с проблемами. Например, если вы сказали следующее:

 public class abc { private abc p; public abc() { p = new abc(); } } 

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

Однако вы все равно можете сделать что-то подобное этому и избежать бесконечной рекурсии. Избегая создания значения во время строительства, вы откладываете его до тех пор, пока не будет вызван метод. На самом деле, это один из распространенных способов реализации одноэлементного шаблона в Java. Например:

 public class abc { private abc p; private abc() { // Private construction. Use singleton method } public static synchronized abc getInstance() { if (p == null) p = new abc(); return p; } } 

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

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

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

Суммируя некоторые ответы здесь.

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

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

Хотя мы говорим о «рекурсии», «выполнение» кода – это то, что мы рассматриваем. Да, это «динамический», если происходит «recursion».

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

В программе статические данные должны быть «конечными» (у вас нет «бесконечного» пространства памяти). Исполнение кода может быть «бесконечным». Но есть исключение. Просто изображение круга цепи.

  • Возвращает нулевой плохой дизайн?
  • Сколько работы должно быть сделано в конструкторе?
  • Когда использовать class в VBA?
  • Что такое Generics в Java?
  • Вызов метода экземпляра из метода classа
  • Почему C ++ STL настолько сильно зависит от шаблонов? (а не на * интерфейсах *)
  • Полиморфизм - определение только двух предложений
  • внутренний class внутри интерфейса
  • Разница между виртуальным, переопределением, новым и закрытым переопределением
  • Принцип разделения сечений - программа для интерфейса
  • «Тени» против «Переопределения» в VB.NET
  • Interesting Posts

    Невозможно использовать ref и out для первого («this») параметра в методах расширения?

    Макрос для экспорта таблиц MS Word в листы Excel

    Использование пользовательской десериализации тела WCF без изменения десериализации шаблона URI

    Тип возврата ‘?:’ (Тернарный условный оператор)

    Оптимизация производительности сборки x86-64 – Выравнивание и outlookирование ветвлений

    Как расширить WIFI из сети Ethernet

    В чем разница между BIOS и прошивкой?

    Какова конкретная проблема с множественным наследованием?

    Нет такого модуля «RestKit» с кокоаподами и быстрыми

    Создание матрицы совпадения

    django – pisa: добавление изображений в PDF-файл

    Ntbackup workalike для adhoc полных резервных копий в Windows 7 бесплатно и предпочтительно с открытым исходным кодом

    Ошибка Crystal Report с IIS – (bobj не определено, отчет Crystal не отображается)

    Каковы наиболее полезные сочетания клавиш Intellij IDEA?

    Windows 8.1: разрешить изменение размера в реальном времени

    Давайте будем гением компьютера.