Java: создание экземпляра локальных внутренних классов - PullRequest
1 голос
/ 02 января 2011

Ниже приведен некоторый игрушечный код, демонстрирующий мой вопрос. Первая - это версия, которая компилируется, а вторая - это версия, которая не компилируется.

В примере 1 , чтобы создать экземпляр InnerClass, я должен создать экземпляр ниже определения класса InnerClass. Это имеет смысл, потому что выше определения класса InnerClass не виден. Однако, скажем ради аккуратности, я хочу создать и использовать экземпляр InnerClass в верхней части foo (). Есть ли способ определить InnerClass на лету до фактического определения класса, чтобы мой код выглядел больше как пример 2 , но был бы допустимым Java?

пример 1

public class OuterClass {
    public void foo() {
        class InnerClass {  

            public InnerClass() {
                // do nothing.
            }

        }

        InnerClass in = new InnerClass(); // Defined below, and compiles!

    }
}

пример 2

public class OuterClass {
    public void foo() {

        InnerClass in = new InnerClass(); // Defined above, does not compile!

        class InnerClass {  

            public InnerClass() {
                // do nothing.
            }

        }

    }
}

Ответы [ 3 ]

3 голосов
/ 02 января 2011

Концептуально, объявление локального класса - это утверждение. Класс не существует, пока инструкция не будет выполнена. Класс также исчезает, когда область, в которой он объявлен, заканчивается. В общем, локальный класс может ссылаться на другие локальные имена областей, поэтому важен порядок выполнения.

void f()
{
  if(true) 
      throw new Error();

  class InnerClass
  { 
    ... 
  }
}

В этом примере оператор объявления InnerClass никогда не достигается, поэтому класс никогда не будет существовать. Ссылаться на это заранее было бы бессмысленно.

Всегда полезно объявить что-либо перед использованием. В Java классы могут иметь циклические зависимости, поэтому Java должна разрешать ссылки на классы из синего цвета - но не делайте этого, если этого можно избежать.

2 голосов
/ 02 января 2011

Вы можете определить внутренний класс вне метода, как

public class OuterClass {
    public void foo() {

        InnerClass in = new InnerClass(); // Defined above, does not compile!


    }

    class InnerClass {  
        public InnerClass() {
            // do nothing.
        }
    }
}
1 голос
/ 02 января 2011

Звучит как большая работа только ради аккуратности. Вот трюк, использующий анонимный внутренний класс, который позволяет вам объявить экземпляр класса, который имеет функциональность, которую вы еще не определили, что отчасти похоже на то, что вы хотите.

Обратите внимание, что ограничение заключается в том, что вы должны были определить интерфейс где-то ранее или повторно использовать существующий интерфейс, такой как Runnable. Вот пример:

public class OuterClass {
    public void foo() {
        // Declaration
        Runnable anonymous;

        // Implementation
        anonymous = new Runnable() {
            public void run() {
                // do nothing.
            }
        };

        // Execution
        anonymous.run();
    }
}
...