Почему класс подкласса класса должен быть статическим, чтобы инициализировать подкласс в конструкторе класса?

Итак, вопрос более или менее, как я писал. Я понимаю, что это, вероятно, не совсем понятно, поэтому я приведу пример.

У меня есть дерево классов и в нем есть класс Node, а пустой конструктор дерева записывается:

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 дает мне ошибку: "Отсутствие экземпляра экземпляра типа RBTree доступно из-за некоторого промежуточного вызова конструктора" для "нового RBTree()" в пустом конструкторе. Однако, если я изменяю RBNode как статический класс, проблем нет.

Итак, почему он работает, когда класс статичен.

BTW, я нашел легкое решение для cunstructor:

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

Итак, я понятия не имею, в чем проблема в первом фрагменте кода.

Ответы

Ответ 1

В основном внутренний класс (без статического модификатора) имеет неявную ссылку на экземпляр своего внешнего класса, поэтому он не может быть создан до создания внешнего класса. Создав один из них в вызове this, он не может ссылаться на внешний класс еще, потому что внешний класс не сконструирован очень сильно, пока не будет вызван вызов super. Случай, который работает для вас, назначение на голову происходит после (неявного) вызова супер, поэтому класс построен достаточно, чтобы получить ссылку на него.

Все эти правила не позволяют вам стрелять себе в ногу, ссылаясь на неинициализированный объект и имея плохие вещи (TM).

Ответ 2

Хорошие новости! Класс подкласса внутреннего класса НЕ должен быть статичным!

Вот техника, объясняемая Генри Вонгом на ранжировании кода, которая работает для внешних классов, которые подклассифицируют внутренние классы. Это сработало для меня, и мне всегда было интересно посмотреть, как дизайнеры языка должны были сузить Java для обработки угловых случаев:)

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

Вот пример:

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

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