2011-02-10 11 views
11

Quando ho classi interne con metodi o campi privati, il compilatore deve creare metodi accessor protetti dal pacchetto sintetico per consentire alla classe esterna di accedere a quegli elementi privati ​​(e viceversa).Esiste un sovraccarico delle prestazioni per una classe interna privata in Java?

Per evitare ciò, di solito, tutti i campi, i metodi e i costruttori sono protetti dal pacchetto anziché privato.

Ma che dire della visibilità della classe stessa? C'è un overhead di

private static class A { 
     A(){} 
} 

contro

static class A { 
     A(){} 
} 

Nota che il costruttore è un pacchetto protetto in entrambi i casi, o se fare il cambiamento privato classe che?

+1

possibile duplicato di [Are Inner Classes lightweight?] (Http://stackoverflow.com/questions/4812464/are-inner-classes-lightweight) – templatetypedef

+0

Mi chiedo se la visibilità ridotta venga sfruttata in qualsiasi modo da Hotspot. Inoltre, mi chiedo se i compilatori java possano utilizzare questo fatto per escludere la classe da considerazioni al di fuori del suo ambito di visibilità. Domanda interessante, ma non penso ci sia alcun beneficio pratico. – Ron

+0

@Ron: il compilatore/IDE controllerà sicuramente la visibilità e renderà errori di compilazione o rimuoverlo dalla funzione di completamento automatico. Mi sto solo chiedendo se qualcosa sta accadendo in fase di runtime. – Thilo

risposta

16

Hai provato a compilarlo e a confrontare il codice byte? Ecco i miei risultati. Per:

public class Example { 
    public static void main(String[] args) { 
    System.out.println("Hello world!"); 
    } 
    private static class A { 
    A(){} 
    } 
} 

È possibile che questo produce i seguenti file * .class:

-rw-r--r-- 1 michaelsafyan staff 238 Feb 10 00:11 Example$A.class 
-rw-r--r-- 1 michaelsafyan staff 474 Feb 10 00:11 Example.class 

Ora, se mi trasferisco i file di classe, eliminare il modificatore private, e ricompilare, ottengo:

-rw-r--r-- 1 michaelsafyan staff 238 Feb 10 00:15 Example$A.class 
-rw-r--r-- 1 michaelsafyan staff 474 Feb 10 00:15 Example.class 

Se si guarda il VM Spec on class files, vedrete che c'è un campo di bit a dimensione costante per specificare i modificatori di accesso, quindi non dovrebbe essere una sorpresa che i file generati siano gli stessi dimensione.

In breve, i modificatori di accesso non influiscono sulla dimensione del codice byte generato (non dovrebbe inoltre avere alcun impatto sulle prestazioni). Dovresti usare il modificatore di accesso che ha più senso.

Devo anche aggiungere che c'è una leggera differenza se si modifica la classe interna dall'essere dichiarata static per non essere dichiarata static, in quanto implica un campo aggiuntivo che fa riferimento alla classe esterna. Ciò richiederà un po 'più di memoria rispetto a quando dichiarassi la classe interna static, ma sarai pazzo per ottimizzare per questo (usa static dove ha senso, e dove hai bisogno che sia non statico, rendilo non statico , ma non convogliare il tuo progetto solo per salvare un puntatore di memoria qui o là).

+0

Findbugs mi ha detto di farlo statica ... – Thilo

+3

@Thilo, è perché non si fa riferimento nulla nella classe esterna; se dovessi accedere ai membri o alle funzioni della classe esterna, allora ci sarebbe un motivo legittimo per renderlo non statico. –

7

Non ci dovrebbero essere differenze di prestazioni tra una classe interna privata e una classe interna non privata.

Non ci dovrebbero essere differenze di prestazioni tra una classe interna statica (privata o meno) e una classe esterna.

C'è una piccola differenza prestazioni tra una classe interna statica e una classe interna non statica. Questa differenza è dovuta al fatto che il caso non statico ha un riferimento nascosto all'istanza della sua classe di chiusura. Questo viene passato come parametro aggiuntivo al costruttore delle classi interne e memorizzato in una variabile nascosta.

+1

E (per coprire tutti i casi) c'è anche una piccola differenza di prestazioni quando by-passando la visibilità privata (dei campi, metodi e costruttori) con le classi interne. – Thilo

+2

@Thilo - Esiste? Perché? AFAIK, le regole di visibilità sono applicate dal compilatore e dal verificatore. Nel momento in cui si esegue (o si compila JIT) i bytecode, i controlli di visibilità sono stati eseguiti e non vi è alcun impatto sulle prestazioni. –

+1

La differenza di prestazioni deriva dall'accesso a un metodo privato tramite un metodo di wrapper sintetico generato dal compilatore anziché accedere direttamente a un metodo protetto da pacchetti. – Thilo

4

È molto improbabile che questo causerà mai un rallentamento significativo.

Un problema di cui tenere conto con le classi interne non statiche è che contengono un riferimento all'istanza della classe di chiusura.

Come tale, questo può causare delle perdite di memoria ', come fattispecie racchiude non può essere garbage collection. Se si passano istanze di classi interne ai chiamanti, si sta anche passando un'istanza della classe che li include.

Questo non è il caso di classi interne statiche!

Fare tutto il pacchetto campi protetti per evitare metodi di sintesi non è consigliabile. Stai rinunciando all'incapsulamento che è una cosa preziosa da avere. Quali sono le tue preoccupazioni? Dimensione dei file di classe per il codice aggiuntivo?

+1

L'incapsulamento è molto importante a livello di pacchetto, quindi non mi sto arrendendo molto qui. I pacchetti esterni (ad esempio il codice di altre persone) non possono vedere la classe in entrambi i casi. – Thilo

+0

@Thilo Solo perché è così ora, non significa necessariamente che rimarrà per sempre in questo modo. L'incapsulamento ti prepara di più per l'imprevisto che per l'atteso. – TheBlastOne

+1

@TheBlastOne: Ancora una volta, non sto affatto rompendo l'incapsulamento qui. Tutto è ancora pacchetto-privato. – Thilo