Разница заключается в проверках времени компиляции и времени выполнения.
В первом случае (время компиляции) вы заявляете, что в этом случае у вас будет ссылка на значение типа abc
.Компилятор узнает об этом, когда проверяет правильную семантику, и, поскольку он знает тип во время компиляции, он не видит проблем с этим.
Во втором случае (во время выполнения) вы фактически создадитезначение для этой ссылки для ссылки.Вот где вы могли бы потенциально получить себе неприятности.Например, если вы сказали следующее:
public class abc {
private abc p;
public abc() {
p = new abc();
}
}
Это может привести к неприятностям по той причине, которую вы указали (рекурсия, которая не содержит базового случая и будет постоянно выделять память до тех пор, пока вы не запустите ВМпространства кучи).
Однако вы все равно можете сделать нечто подобное и избежать бесконечной рекурсии.Избегая создания значения во время построения, вы откладываете его до тех пор, пока не будет вызван метод.Фактически, это один из распространенных способов реализации шаблона синглтона в 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;
}
}
Это совершенно верно, потому что вы создаете только один новый экземпляр значения, и поскольку во время выполнения будет загружен класс уже, он будет знать, что тип переменной экземпляра является действительным.