2013-06-06 8 views
8

Si prega di controllare il codice Java sotto:Come utilizzare le variabili membro con interfacce e le implementazioni anonimi

public class Test 
{ 
    public static void main(String arg[]) throws Throwable 
    { 
     Test t = new Test(); 
     System.out.println(t.meth().s);   //OP: Old value 
     System.out.println(t.meth().getVal()); //OP: String Implementation 
    } 
    private TestInter meth() 
    { 
    return new TestInter() 
    { 
     public String s = "String Implementation"; 
     public String getVal() 
     { 
     return this.s; 
     } 
    }; 
    } 
} 
interface TestInter 
{ 
    String s = "Old value"; 
    String getVal(); 
} 

Come vedi ho creato un'interfaccia in forma anonima. Quando accedo direttamente alla variabile di interfaccia, mostrerà "Vecchio valore".

t.meth(). S => "Valore precedente"

accedervi attraverso il GetVal() restituisce valori corretti,

t.meth(). GetVal() => "Stringa Implementazione "

Non capisco come funziona questo codice, qualcuno può spiegarmelo?

risposta

7

Il s variabile dichiarata nell'interfaccia è completamente separata dalla variabile s che avete dichiarato nella classe interna anonima.

Le variabili di interfaccia sono in realtà solo progettate per essere costanti - non fanno parte dell'API che ogni implementazione deve fornire. In particolare, sono implicitamente statici e definitivi.

Dal JLS section 9.3:

Ogni dichiarazione di campo nel corpo di un'interfaccia è implicitamente pubblico, statica e definitiva. È consentito specificare in modo ridondante alcuni o tutti questi modificatori per tali campi.

Il fatto che ti sei collegato a campo tramite un'istanza implementazione è irrilevante - questo codice:

System.out.println(t.meth().s); 

è efficace:

t.meth(); 
System.out.println(TestInter.s); 

vorrei vivamente di evitare l'uso di variabili nelle interfacce eccetto per costanti originali ... e anche allora, solo dove ha davvero senso. Non è chiaro cosa stai cercando di ottenere, ma dichiarare un campo in un'interfaccia non è un buon modo per arrivare a IMO.

+0

Si * sconsiglia l'uso * o * si consiglia di evitare * variabili nelle interfacce, giusto? – Fildor

+0

@Fildor: risolto, grazie. –

+0

@JonSkeet ma anche se estende una normale classe invece di un'interfaccia, ottiene gli stessi risultati. L'ho provato ho ragione, è quello che ho inquadrato nella mia risposta ... per favore correggimi se ho torto ... grazie :) – pinkpanther

3

Non c'è niente come variable-overriding come method overriding in java. Denominare un nuovo tipo per subclass, quindi si otterrà il "String Implementation", quando si accede tramite il tipo di riferimento della sottoclasse.

Il privilegio di accesso protected significa solo che è possibile accedere alla variabile in una sottoclasse ma che non può essere ignorata.

Anche se si utilizza il normale class anziché interface, questo non funzionerà. Quando si fa riferimento utilizzando super tipo di classe, si ottiene solo le variabili instance da super tipo e così via .... Questo esempio illustra il primo caso: Esempio:

public class Tester 
{ 
    public static void main(String arg[]) throws Throwable 
    { 
     Tester t = new Tester(); 
     System.out.println(t.meth().s); // it prints "Old value" because your type is TestInter   
    } 
    private TestInter meth() 
    { 
    return new TestInter() 
    { 
     protected String s = "String Implementation"; 

    }; 
    } 
} 
class TestInter 
{ 
    protected String s = "Old value"; 

} 

Questo esempio illustra il secondo caso: esso stampa "String Implementation"

public class Tester 
{ 
    public static void main(String arg[]) throws Throwable 
    { 
     Tester t = new Tester(); 
     System.out.println(t.meth().s);   
    } 
    private SubTestInter meth() 
    { 
    return new SubTestInter(); 
    } 
} 
class SubTestInter extends TestInter{ 
     protected String s = "String Implementation"; 
} 
class TestInter 
{ 
    protected String s = "Old value"; 

} 
1
When i access a interface variable directly 

Hai il riferimento di tipo di interfaccia, è per questo che si riferisce di interfacciarsi direttamente e si ottiene "Valore precedente"

Accessing getVal() method, showing proper values 

Quando si richiama il metodo GetVal() si fa riferimento a effettiva attuazione di questo metodo e questo è il motivo per cui GetVal di effettiva attuazione è chiamato. Ciò significa istanza corrente con il seguente valore:

public String s = "String Implementation"; 
1

I campi dichiarati in un'interfaccia sono costanti.

Così, quando si scrive

interface TestInter 
{ 
    String s = "Old value"; 
    String getVal(); 
} 

si dichiara un s costante. Ecco perché t.meth().s è la stampa Old value

t.meth().getVal() fase di stampa del contenuto del campo s della vostra classe anonima.

Problemi correlati