Возможный дубликат:
Как класс может иметь член своего собственного типа, не эта бесконечная рекурсия?
Код:
public class Test2{
private Test2 subject = new Test2(); //Create Test2 object in Test2
private int num;
}
Вопросы:
Почему Java разрешает выполнение вышеуказанного кода, а C ++ — нет?
Создает ли код выше бесконечное количество объектов? поскольку Test2
сам содержит Test2
объект, который снова содержит Test2
объект, который сам по себе имеет Test2
объект и тд.
Ключевое различие между этими двумя языками в отношении вашей проблемы заключается в том, что Java — это язык со ссылочной семантикой (за исключением примитивных типов), а C ++ — это язык со семантикой значений, которая позволяет ссылочную семантику посредством ссылок и указателей.
Синтаксис, который выглядит аналогичный в обоих языках имеет совершенно разные значения, когда в Java вы создаете ссылка (Test2 x = new Test2();
) эквивалентная конструкция в C ++ будет использовать указатель (Test2 *x = new Test2();
).
Ключевым отличием является то, что просто обеспечить ссылочную семантику поверх семантики значений с помощью указателей, но невозможно обеспечить семантику значений поверх (чистой) ссылочной семантики. Некоторые из последствий этого утверждения включают в себя неспособность контролировать расположение объектов в Java в памяти или локальность данных (для чего-либо, кроме примитивных типов и массивов примитивных типов), в то время как в другом направлении более тонкий контроль объектов в C ++ позволяет имитировать объекты Java.
По вопросу 2 — если вы запустите этот код, вы получите StackOverflowException => Да, он создает бесконечное число объектов (хорошо, что он пытается …)
public class Test2 {
private Test2 subject = new Test2(); //Create Test2 object in Test2
public static void main(String[] args) throws Exception {
Test2 t = new Test2();
}
}
subject
вот ссылка к примеру Test2
, Если вы попытаетесь запустить его, код быстро исчерпает некоторый ресурс (возможно, место в стеке, возможно, пространство в куче).
Почему Java разрешает выполнение вышеуказанного кода, а C ++ — нет?
С 2011 года C ++ также позволяет инициализировать членов класса в своих объявлениях.
Однако это не допустит этого случая: вы можете создавать экземпляры только полных типов, а тип класса является неполным в определении класса, поэтому его придется инициализировать в конструкторе или путем вызова функции:
class Test;
Test * make_test();
class Test {
// Test is incomplete, so "new Test" is not possible here
Test * test = make_test();
};
// Test is complete, so we can instantiate it here
Test * make_test() {return new Test;}
В Java нет понятия неполных типов, поэтому создание экземпляра класса может осуществляться везде, где вам разрешено создавать экземпляры любого класса.
Создает ли код выше бесконечные объекты?
Да, попытка создания такого класса привела бы вашу программу к рекурсивной смертельной спирали.
Если вы объявите subject
как существо static
, вы получите готовую версию инициализации шаблона Singleton, которая не вытащит вас из ресурсов.
так как вы можете иметь несколько конструкторов, это разрешено.
если у вас есть только один конструктор, это действительно приведет к бесконечному циклу.
public class Test{
private Test a;
public Test(String s){
this.a=new Test();
}
public Test(){
}
}