2010-04-29 13 views
13

Entonces, la pregunta es más o menos como escribí. Entiendo que probablemente no esté del todo claro, así que daré un ejemplo.¿Por qué una clase de subclase de una clase tiene que ser estática para inicializar la subclase en el constructor de la clase?

tengo Árbol de clase y en él no es el nodo de clase, y el constructor vacío del árbol está escrito:

public class RBTree { 
    private RBNode head; 

    public RBTree(RBNode head,RBTree leftT,RBTree rightT){ 
     this.head=head; 
     this.head.leftT.head.father = head; 
     this.head.rightT.head.father = head; 
    } 

    public RBTree(RBNode head){ 
     this(head,new RBTree(),new RBTree()); 
    } 

    public RBTree(){ 
     this(new RBNode(),null,null); 
    } 

    public class RBNode{ 
     private int value; 
     private boolean isBlack; 
     private RBNode father; 
     private RBTree leftT; 
     private RBTree rightT; 
    } 
} 

Eclipse me da el error: "Ningún caso encerrando de tipo RBTree está disponible debido a alguna invocación de constructor intermedio "para el" nuevo RBTree() "en el constructor vacío. Sin embargo, si cambio el RBNode para que sea una clase estática, no hay problema.

¿Por qué funciona cuando la clase es estática?

Por cierto, he encontrado una solución fácil para el cunstructor:

public RBTree(){ 
    this.head = new RBNode(); 
} 

Por lo tanto, no tienen idea de lo que es el problema en la primera pieza de código.

Respuesta

24

Básicamente una clase interna (sin el modificador estático) tiene una referencia implícita a una instancia de su clase externa, por lo que no se puede crear hasta que se cree la clase externa. Al crear uno en la llamada al this, todavía no puede hacer referencia a la clase externa porque la clase externa no está construida en absoluto hasta después de la llamada a super. El caso que funcione para usted, la asignación a la cabecera sucede después de la llamada (implícita) al súper, por lo que la clase se construye lo suficiente como para obtener una referencia.

Todas estas reglas evitan que se pegue un tiro en el pie al hacer referencia a un objeto no inicializado y que ocurran cosas malas (TM).

+2

Esta limitación no me permite escribiendo código limpio Tengo que inventar soluciones feas. Sin embargo, todavía puedo acceder a variables no inicializadas incluso con esta limitación. Cuando escribes un código feo, es aún más fácil. Por lo tanto, para evitar que "tiremos a nuestro propio pie", java debe estar prohibido en el JLS. No hay nada de malo en crear una instancia interna. Inner puede tener su referencia al encerrar porque el objeto ya está allí. El hecho de que no esté inicializado no lo hace mal. De lo contrario, puede pensar que es peligroso inicializar el objeto antes de inicializarlo. – Val

0

¡Buenas noticias! ¡La clase de subclase de una clase interna NO tiene que ser estática!

Aquí hay una técnica explicada por Henry Wong en rancho de código que funciona para las clases externas que subclasan las clases internas. Funcionó bien para mí y siempre es divertido ver cómo los diseñadores del lenguaje tenían que contorsionarse de Java para manejar los casos de esquina :)

http://www.coderanch.com/t/588820/java/java/Extend-class-code-top-level#2681401

Aquí está el ejemplo:

class Demo extends Main.Inner{ 
    public Demo(Main outer) { 
     outer.super(); 
    } 

    void method(){ 
     System.out.println(a); 
    } 
} 
Cuestiones relacionadas