2010-05-27 6 views
5

Considerate si ha la seguente classeClasse membro statica: dichiarare la classe private e il membro della classe package-private?

public class OuterClass { 
    ... 

    private static class InnerClass { 
     int foo; 
     int bar; 
    } 
} 

Credo di aver letto da qualche parte (ma non il Java Tutorial ufficiale) che se avessi dichiarare le classi membro statiche attributi privati, il compilatore ha dovuto generare una sorta di metodi di accesso in modo che la classe esterna possa effettivamente accedere agli attributi della classe membro statica (che è effettivamente una classe di livello principale del pacchetto).

Qualche idea al riguardo?

risposta

4

Sì, è vero. Almeno per il javac del sole. Date un'occhiata al seguente esempio:

public class OuterClass { 

    public static void main(String... args) { 
     InnerClass.foo = 7; 
     System.out.println(InnerClass.foo); 
    } 

    private static class InnerClass { 
     private static int foo; 
     private static int bar; 
    } 
} 

$ javap -c OuterClass\$InnerClass 
Compiled from "OuterClass.java" 
class OuterClass$InnerClass extends java.lang.Object{ 
static int access$002(int); 
    Code: 
    0: iload_0 
    1: dup 
    2: putstatiC#1; //Field foo:I 
    5: ireturn 

static int access$000(); 
    Code: 
    0: getstatiC#1; //Field foo:I 
    3: ireturn 

} 

Si definisce un static int access$002(int) per impostare il valore, e un static int access$000() per ottenere il valore. Anche il setter restituisce il valore, presumibilmente per compilare facilmente someVariable = InnerClass.foo = 5.


$ javap -c OuterClass 
Compiled from "OuterClass.java" 
public class OuterClass extends java.lang.Object{ 
public OuterClass(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: bipush 7 
    2: invokestatiC#2; //Method OuterClass$InnerClass.access$002:(I)I 
    5: pop 
    6: getstatiC#3; //Field java/lang/System.out:Ljava/io/PrintStream; 
    9: invokestatiC#4; //Method OuterClass$InnerClass.access$000:()I 
    12: invokevirtual #5; //Method java/io/PrintStream.println:(I)V 
    15: return 

} 

Alla linea 2 e alla linea 9 chiama il setter (access$002) e getter (access$000) rispettivamente.


Si noti inoltre che introduce solo questi metodi di accesso se sono necessari. Il campo bar, ad esempio, non è mai stato utilizzato al di fuori della classe, quindi il compilatore ha generato solo un getter/setter per il campo foo.

+0

+1 Ottima risposta. Quindi dovresti sempre dichiarare la classe membro statica privata/pacchetto-privata/protetta e lasciare i campi membro pacchetto-privato? – helpermethod

+1

Metodo @Helper - No - vedere la mia risposta. –

+0

Si dovrebbe fare ciò che è appropriato per il campo in questione. Se ha senso averlo privato, renderlo privato. Non preoccuparti dei problemi di prestazioni, ecc., Finché non conta, quindi profila il programma nella sua interezza e scopri dove ottieni il massimo dall'ottimizzazione. (Non sarà certamente in casi come questi). – aioobe

3

Qualche idea al riguardo?

la risposta di @ aioobe indica che eri corretto.

Tuttavia, probabilmente non fa differenza. È probabile che il compilatore JIT in linea la chiamata al metodo di accesso e il codice nativo risultante sarà identico a un semplice recupero. Anche se il compilatore JIT non lo fa, è probabile che la penalizzazione delle prestazioni sia insignificante nel contesto di un'applicazione Realworld.

Ciò che dice è che non c'è nessun punto "ottimizzare" il codice prematuramente usando i modificatori di accesso che dicono qualcosa di diverso da ciò che si vuole veramente esprimere.