2015-01-02 4 views
13

У меня есть недоразумение о том, что такое анонимный класс в Java. Рассмотрим следующий простой пример:Почему анонимный класс в статическом контексте действителен

public static void main (String[] args) throws java.lang.Exception 
{ 
    B b = new B(){ }; 
    System.out.println(b.b); 
} 

interface B{ int b = 1; } 

DEMO

Почему код компилировать? JLS, chapt 15 говорит:

Анонимный класс всегда является внутренним классом (§8.1.3); она никогда не статический

JLS, chapt 8 Но

Внутренний класс вложенный класс, который не является явно или неявно объявлен статическим.

Таким образом, анонимный класс является внутренним классом. Но мы используем их в статическом контексте. Почему это правильно?

+0

'B b = new B() {};' не является анонимным классом.И он работает, потому что он * используется в * статическом контексте, он объявляет внутренний класс статическим, что запрещено. –

+0

@Shywim Итак, какой тип был объектом, созданным 'new B() {}'? –

ответ

7

Класс может быть создан в статическом контексте, не будучи объявлен статическим, и это то, что происходит Вот. Давайте посмотрим на то, что было объявлено статической, и создаются в статическом контексте означает:

Разница между анонимным классом, созданным в статическом контексте и нестатическая контексте имеет ли оно охватывающую экземпляр:

Если с анонимным класс, то:

  • Если выражение создания экземпляра класса происходит в статическом контексте, то я не не сразу ограждающим экземпляр.

  • В противном случае непосредственным экземпляром i является это.

Вложенный класс, который объявлен статический позволяет статические члены:

Внутренний класс вложенный класс, который не является явно или неявно объявляется статической.

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

Говоря вложенный класс, который «неявно объявлен статическим», это относится к вещам, как классы в интерфейсах:

класс член интерфейса неявно статический (§9.5), так что никогда не считается внутренним классом.

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

Поскольку анонимные классы не объявлены статическими, обе кавычки в вопросе согласованы.

3

Вы должны различать между анонимными и внутренними классами

С этим утверждением вы создаете класс, реализующий интерфейс B. Класс не имеет имени, так это называется анонимным классом. javac компиляция создаст файл класс со следующим именованием правило YourClass $ 1.class (где 1 представляет собой порядковый номер, на основе числа анонимных классов в YourClass.

B b = new B(){ }; 

класс, созданный new B(){ } не может быть объявлен как статический («анонимный класс всегда внутренний класс (§8.1.3), она никогда не бывает статичным»)..

статический вложенный пример класса

class YourClass { 
    static class StaticNestedClass { 
    } 
} 

нестатический вложенный класс пример

class YourClass { 
    // An inner class is a nested class that is not explicitly or implicitly declared static. 
    class InnerClass { 
    } 
} 

Существует два типа вложенных классов: статические и нестатические. Вложенные классы, объявленные статическими, являются так называемыми static nested classes, тогда как вложенные классы, не объявленные как статические, являются так называемыми inner classes.

+1

Мы ищем ответы со ссылкой на JLS вместо вашего понимания. – nhahtdh

+2

Это базовое введение во внутренние классы, но не затрагивает вопрос вообще. – chrylis

1

B внутренний интерфейс . Поскольку такой B неявно статичен, и вы можете ссылаться на B в статическом контексте. (От JLS 8.5.1: Пользовательский интерфейс неявно статичен (§9.1.1).)

Но анонимный класс, созданный через B не статичен, а если ссылки из не статического контекста, вы могли бы получить доступ к внешнему объекту:

public class Main{ 

    public static void main(String[] args) throws java.lang.Exception { 
     B b = new B() { 

      @Override 
      public Ess3 getParent() { 
       //return Ess3.this; ERROR : non static variable cannot be referenced from static context 
       return null; 
      } 
     }; 
     System.out.println(b.b); 
    } 

    interface B { 

     int b = 1; 
     Ess3 getParent(); 
    } 

    /* a non static method */ 
    void foo() { 
     B b = new B() { 

      @Override 
      public Ess3 getParent() { 
       return Ess3.this; // this anonymous class is not static 
      } 

     }; 

    } 
} 

В вашем примере, вы могли бы подумать вам создал статический анонимный внутренний класс, потому что вы его создали:

  • от статического вложенного интерфейса
  • в статическом контексте - так, не имея доступа к внешнему объекту

Но это же заявление в не статическом контексте доказывает, что статический вложенный интерфейс создает нон статический анонимный класс

+0

Пожалуйста, процитируйте JLS, чтобы укрепить ваше требование. – nhahtdh

+0

@nhahtdh: Я думал, что OP уже процитировал соответствующую часть JLS, но я прочитал ее в другом ответе. Сообщение редактировалось –

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