¿Cómo puede una clase tener un miembro de su propio tipo, no es esta recursión infinita?

Digamos que defino una clase que tiene como miembro una variable del mismo tipo que ella.

public class abc { private abc p; } 

Esto realmente funciona, para mi sorpresa.

Por qué creo que no debería: al crear una instancia de abc , contiene una variable de tipo abc , que contiene una variable de tipo abc , que contiene una variable de tipo abc , que …..

Obviamente estoy equivocado, ¿podría alguien aclararme cómo?

Solo declaras la variable y no la creas. Intenta crearlo en la statement o en el constructor y avísame qué sucede:

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

Por cierto, si no lo creas en la clase, sino que aceptas una referencia a él en un método getter o en un parámetro constructor, tu código funcionará perfectamente. Así es como funcionan algunas listas vinculadas.

La diferencia radica en las comprobaciones en tiempo de comstackción frente a tiempo de ejecución.

En el primer caso (tiempo de comstackción), declara que tendrá una referencia a un valor de tipo abc en este caso. El comstackdor lo tendrá en cuenta cuando compruebe la semántica adecuada, y dado que conoce el tipo en el momento de la comstackción, no ve ningún problema con esto.

En el segundo caso (tiempo de ejecución), realmente creará un valor para esta referencia para referirse a. Aquí es donde potencialmente podría meterse en problemas. Por ejemplo, si dijiste lo siguiente:

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

Esto podría llevarlo a problemas por la razón exacta que citó (recursión que no contiene un caso base y asignará memoria de manera continua hasta que haya ejecutado la VM fuera del espacio de almacenamiento dynamic).

Sin embargo, aún puede hacer algo similar a esto y evitar la recursión infinita. Al evitar crear el valor durante la construcción, lo pospones hasta que se solicite un método. De hecho, es una de las formas comunes de implementar el patrón singleton en Java. Por ejemplo:

 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; } } 

Esto es perfectamente válido porque solo crea una nueva instancia del valor, y dado que el tiempo de ejecución ya habrá cargado la clase, sabrá que el tipo de la variable de instancia es válido.

Cuando desee modelar algunos escenarios del mundo real, es posible que deba usar esta noción. Por ejemplo, piense en la twig de un árbol. La twig de un árbol puede tener n cantidad de twigs en ella. O desde el conocimiento de informática, piense en el Nodo de una lista vinculada. Un nodo tendrá referencia al nodo contiguo. Al final, el siguiente contendrá un nulo para indicar el final de la lista.

Por lo tanto, esto es solo una referencia, lo que indica que este tipo podría referirse a uno propio. Nada mas.

Resumiendo algunas de las respuestas aquí.

La clase contiene referencias a una de su tipo. La mejor analogía en el mundo real sería una búsqueda del tesoro. Un lugar de Clue tiene algunos datos y una pista que conduce a otro lugar de pista que nuevamente conoces repeticiones.

No está diciendo que un lugar clave tenga otro lugar clave, del tipo que pareces deducir.

Mientras estamos hablando de “recursión”, la “ejecución” del código es el punto que estamos considerando. Sí, es “dynamic” si ocurre una “recursión”.

En la statement de tipo, una variable que contiene un miembro, que es el tipo de variable contenedora, es “estática”. Por ejemplo, un cuadro puede contener otro cuadro dentro de él, y así sucesivamente. Pero finalmente hay una caja más pequeña que no contiene nada. Para una cadena de vagones de ferrocarril, cada vagón tiene un miembro para el próximo vagón excepto el último vagón.

En el progtwig, los datos estáticos deben ser “finitos” (no tiene espacio de memoria “infinito”). La ejecución del código puede ser “infinita”. Pero hay una excepción. Solo imaginando un círculo de cadena.