2015-01-02 26 views
13

Ho un malinteso su cosa sia una classe anonima in Java. Si consideri il seguente esempio semplice:Perché una classe anonima in un contesto statico è valida

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

Perché il codice di compilazione? Il JLS, chapt 15 dice:

Una classe anonima è sempre una classe interna (§8.1.3); non è mai statica

Ma la JLS, chapt 8

una classe interna è una classe annidata che non è esplicitamente o implicitamente dichiarato statico.

Quindi la classe anonima è una classe interiore. Ma li usiamo nel contesto statico. Perché è corretto qui?

+0

'B b = nuovo B() {};' non è una classe anonima.E funziona perché è * usato in * un contesto statico, sta dichiarando la classe interna stessa statica che è proibita. –

+0

@Shywim Quindi quale tipo era l'oggetto creato da 'new B() {}'? –

risposta

7

Una classe può essere creato in un contesto statico, senza essere dichiarato statico, e questo è ciò che sta accadendo Qui. Diamo un'occhiata a ciò che viene dichiarato statica, e ha creato in un contesto statico significa:

La differenza tra una classe anonima creata in un contesto statico e un contesto non statico è se ha un'istanza allegando:

Se C è una classe anonima, quindi:

  • Se l'espressione creazione dell'istanza classe avviene in un contesto statico, allora i ha non immediatamente racchiude esempio.

  • Altrimenti, l'istanza di i immediatamente racchiusa è questa.

Una classe annidata che viene dichiarata static consente ai membri statici:

Una classe interna è una classe annidata che non sia esplicitamente o implicitamente dichiarata statica.

Una classe nidificata che non è una classe interna può dichiarare membri statici liberamente, in conformità con le solite regole della lingua Java .

Dicendo una classe annidata che è 'implicitamente dichiarata static', si riferisce a cose come le classi all'interno di interfacce:

Una classe membro di un'interfaccia è implicitamente statico (§9.5) quindi non è mai considerata una classe interiore.

classi anonimi non sono dichiarate static (né in modo esplicito con una parola chiave, o implicitamente come essere all'interno di un'interfaccia), e quindi non consentono la dichiarazione di membri statici. Possono tuttavia essere creati all'interno di un contesto statico, il che significa che non si riferiscono a un'istanza che li include.

Poiché le classi anonime non sono dichiarate statiche, entrambe le virgolette nella domanda sono coerenti.

3

Si deve distinguere tra classi anonime e interne

Con questa affermazione si crea una classe che implementa l'interfaccia B. La classe non ha un nome così si chiama una classe anonima. Il javac compilazione creerà un file di classe con denominazione seguente regola YourClass $ 1.class (dove 1 è un numero sequenziale, in base al numero di classi anonime in YourClass.

B b = new B(){ }; 

La classe creato da new B(){ } non può essere dichiarato come statica ("una classe anonima è sempre una classe interna (§8.1.3), non è mai statico")..

un esempio di classe innestata statica

class YourClass { 
    static class StaticNestedClass { 
    } 
} 

un esempio classe innestata non statica

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

Esistono due tipi di classi nidificate: statiche e non statiche. Le classi annidate dichiarate statiche sono chiamate static nested classes, mentre le classi annidate non dichiarate come statiche sono chiamate inner classes.

+1

Cerchiamo risposte che citino il JLS invece che dalla vostra comprensione. – nhahtdh

+2

Questa è un'introduzione di base alle classi interiori, ma non affronta affatto la domanda. – chrylis

1

B è un'interfaccia interna . Poiché tale B è implicitamente statica e puoi fare riferimento a B in un contesto statico. (da JLS 8.5.1: Un'interfaccia membro è implicitamente statica (§ 9.1.1).)

Ma la classe anonima creata attraverso B non è statica, e se si fa riferimento da un contesto non statica, si potrebbe ottenere l'accesso all'oggetto esterno:

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 
      } 

     }; 

    } 
} 

Nel tuo esempio, si potrebbe pensare che si creato una classe interna anonima statica, perché è stato creato:

  • da una statica interfaccia annidata
  • in un contesto statico - in modo che non hanno accesso all'oggetto esterno

Ma stessa dichiarazione in un contesto non statica dimostra che un'interfaccia innestata statica crea una classe anonima non statica

+0

Si prega di citare da JLS per rafforzare la richiesta. – nhahtdh

+0

@nhahtdh: Pensavo che OP avesse già citato la parte rilevante di JLS ma l'ho letta in un'altra risposta. Post modificato –

Problemi correlati