2015-07-10 1 views
1

У меня есть код вроде следующего:Почему объект вложенного класса нельзя использовать в качестве параметра конструктора супертипа?

class A { 
    final Object data; 

    A(Object _data) { 
     data = _data; 
    } 

    class B extends A { 
     B() { 
      super(new C()); 
     } 

     class C { } 
    } 
} 

Я получаю следующее сообщение об ошибке:

Cannot reference 'C' before supertype constructor has been called

Я не понимаю, почему это не представляется возможным.

Есть ли способы обхода? Я хочу, чтобы data был окончательным, а классы - вложенными, так как они находятся в коде выше (я не хочу создавать для каждого класса другой файл, потому что классы довольно малы и в моем реальном коде было бы логичнее для них чтобы быть вложенным)

+1

С должным уважением, я задаю вопрос вашему дизайну. Внутренний класс, который расширяет внешний класс, это странно ... Не желая иметь разные файлы для классов, вы летите против java-конвенций. Таким образом, нет очевидного обходного пути, так как C не может быть статическим, он должен иметь экземпляр B. –

ответ

2

Проблема заключается в том, что не статические внутренние классы необходим экземпляр внешнего класса, прежде чем они могут быть созданы. Вот почему вы можете даже получить доступ к полям внешнего класса непосредственно во внутреннем классе.

Сделайте внутренние классы static, и он должен работать. В общем, хороший шаблон для использования статических внутренних классов вместо нестатического. Дополнительную информацию см. В статье «Эффективная Java-статья» Джошуа Блоха.

class A { 

    final Object data; 

    A(final Object _data) { 
    data = _data; 
    } 

    static class B extends A { 

    B() { 
     super(new C()); 
    } 

    static class C { 
    } 
    } 
} 
+0

Спасибо! Это то, чего я хотел. –

4

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

Вот еще один пример - прочитать комментарии:

class Base { 
    Base(Object x) {} 
} 

class Outer extends Base { 

    Outer() { 
     super(new Nested()); // No problem 
    } 

    Outer(int ignored) { 
     super(new Inner()); // Effectively this.new Inner() 
    } 

    Outer(boolean ignored) { 
     super(new Outer().new Inner()); // Fine 
    } 

    Outer(long ignored) { 
     super(new Nested(this)); // Explicitly passing this 
    } 

    static class Nested { 
     Nested() {} 

     Nested(Object ignored) {} 
    } 

    class Inner { 
    } 
} 
+0

Спасибо за объяснение! –

2

Здравствуйте, извините, не оставьте комментарий.

Я не хочу, чтобы создать другой файл для каждого класса, потому что классов достаточно малы

У меня был профессор, который всегда говорил «Есть никогда не бывает слишком маленькие классы, только слишком большие "

Если вы сохраняете и все еще хотите, чтобы классы были вложенными, вы можете создавать статические классы класса C в зависимости от вашей цели. Но я настоятельно рекомендую задать вопрос вашему дизайну.

Смежные вопросы