2012-09-16 19 views
5

Lo scopo di questa query è confrontare un aspetto di Java e C++, che ha a che fare con l'operatore "nuovo".Poiché tutti gli oggetti sono creati con "nuovo" in Java, significa che sono tutti creati sull'heap?

Ora, so che in C++ ci sono due modi per creare oggetti; con o senza l'operatore "nuovo". In assenza di tale operatore, lo spazio non è allocato nella regione heap, mentre, in sua presenza, lo spazio viene allocato nella regione heap.

Che dire di Java? Ho notato che l'operatore "nuovo" è usato per creare ogni oggetto. Anche gli array vengono creati con l'operatore "nuovo". Significa che in Java c'è solo un posto in cui gli oggetti possono esistere - cioè la regione dell'heap?

Grazie.

+3

In generale, lo stesso nome per una parola chiave non implica la somiglianza - a volte lo è solo. – Linuxios

+0

Dovrei scegliere una risposta? Non lo sapevo – softwarelover

+0

(Ho rimosso il tag C++ e reso il titolo più raffinato, anche se di lunga durata. Ora, se la domanda riguardava C# - che utilizza ancora 'new' per i Value Type che possono evitare" stack allocation "- le risposte sarebbero * diverso * come C# non è Java proprio come Java non è C++.) –

risposta

6

Sì, il nuovo operatore alloca sempre la memoria per l'oggetto sull'heap. A differenza del C++, gli oggetti in Java non possono essere creati nello stack.

+2

La nozione di heap è specifica dell'implementazione, poiché la specifica della macchina virtuale non limita intenzionalmente le opzioni di archiviazione. – oldrinb

+2

+1 Direi invece "A differenza del C++, non c'è modo in Java di dire che vuoi un oggetto allocato nello stack" –

+0

Commentando felicemente in futuro. ;) –

4

tipi primitivi locali e locali riferimenti ai tipi di oggetto, sia occupano memoria "stack", come fanno entrambi quando passati come parametri ai metodi.

Tutti gli oggetti stessi esistono nell'equivalente di un "heap".

+1

@softwarelover l'archiviazione di oggetti Java è intenzionalmente lasciata non specificata dalla specifica della macchina virtuale; questo è sfruttato dalle mie macchine virtuali come HotSpot che usano l'analisi di escape per sfruttare al meglio l'allocazione dello stack per gli oggetti :-) – oldrinb

+1

Sta dicendo che all'interno di qualsiasi blocco (ad es. il corpo della funzione) esistono alcune variabili locali. Sia che siano primitive o oggetti allocati, entrambi hanno una certa presenza nello stack: le primitive sono completamente nello stack (ad esempio, un 'int' di 4 byte è 4 byte nello stack). Gli oggetti allocati possono essere convenientemente pensati come puntatori in pila; occupano spazio sulla pila proprio come farebbe un puntatore, che viene usato per fare riferimento all'oggetto reale puntato in memoria (creato usando 'new'). Come sottolinea @oldrinb, questo potrebbe non essere esattamente ciò che sta accadendo, ma è effettivamente ciò che sta accadendo. – pickypg

+0

Grazie pickypg, ora capisco cosa ha detto Alnitak. Non ho letto attentamente .. – softwarelover

2

Tutti gli oggetti Java (cioè ogni cosa con riferimento) sono allocati nel mucchio dal punto di vista dell'applicazione e il programmatore . Java non supporta l'allocazione esplicita di oggetti nello stack. I riferimenti agli oggetti possono essere archiviati sia nei nodi heap (cioè i campi di classe o istanza) e i frame di stack (cioè le variabili locali, ecc.).

In realtà, ci sono alcuni modi che prima classe gli oggetti Java possono essere creati in Java che non lo fanno coinvolgono utilizzando la parola chiave new.

  • La sintassi inizializzatore { ... } matrice può essere utilizzato in una dichiarazione di matrice senza la parola chiave new.

  • Un valore letterale String comporta la creazione di un oggetto String (in fase di caricamento della classe).

  • La conversione di boxing (in genere) crea un nuovo oggetto wrapper senza un esplicito new o una chiamata di metodo.

  • Il metodo riflettente newInstance e metodi simili creano oggetti senza un esplicito new.

  • Sotto il cofano, l'implementazione della serializzazione Java utilizza un metodo speciale nella classe Unsafe per creare oggetti senza eseguire alcun costruttore dichiarato.

  • È inoltre possibile creare oggetti Java nel codice nativo utilizzando gli apis JNI/JNA.

(V'è un argomento forte che gli ultimi due sono "non Java", ma sono degni di nota in ogni caso. E i casi letterali e di auto-boxing String coinvolgono il codice Java che utilizza new sotto il cofano.)


1 - Ci può essere più di un mucchio, anche se questo è trasparente per l'applicazione.

2 - Le ultime JVM di Hotspot hanno una funzione sperimentale di "analisi di fuga" che determina se gli oggetti "scappano" dal contesto in cui sono creati. Gli oggetti che non sfuggono potrebbero essere allocati in modo sicuro nello stack. Ancora una volta, questa ottimizzazione è trasparente per l'applicazione.

+0

Sebbene questa sia una buona informazione, non risponde alla domanda principale di "in pila/sull'heap". Aggiungi "indipendentemente dal fatto che gli oggetti vengano sempre creati nell'heap" e questa sarebbe la migliore risposta. – EdC

+0

@ EDC: è d'accordo con te! – softwarelover

0

In Java, tutti gli oggetti vengono allocati dinamicamente su Heap. Questo è diverso dal C++ in cui gli oggetti possono essere allocati in memoria sia su Stack che su Heap. In C++, quando assegniamo abject usando new(), l'abject è allocato su Heap, altrimenti su Stack se non globale o statico.

In Java, quando dichiariamo solo una variabile di un tipo di classe, viene creato solo un riferimento (la memoria non è allocata per l'oggetto). Per allocare memoria ad un oggetto, dobbiamo usare new(). Quindi all'oggetto viene sempre assegnata memoria su heap.

Esempio 1: Fornire l'errore di compilazione.

class Test { 
    void show() { 
     System.out.println("Test::show() called"); 
    } 
}  
public class Main { 
    public static void main(String[] args) { 
     Test t; 
     t.show(); // Error here because t is not initialed 
    } 

Esempio 2: memoria Allocazione utilizzando new() rende sopra funzionano programma.

class Test { 
    void show() { 
     System.out.println("Test::show() called"); 
    } 
}  
public class Main { 
    public static void main(String[] args) { 
     Test t = new Test(); //all objects are dynamically allocated 
     t.show(); // No error 
    } 
} 
Problemi correlati