2009-07-02 8 views
5

C'è un modo in Java che una dichiarazione comeIn Java, la novità è sempre nuova?

Thing thing = new Thing(); 

potrebbe non risultato in un nuovo oggetto viene creato (vale a dire un modo che potrebbe finire per thing punta a un oggetto già esistente)?

+2

Perché lo chiedi? Stai ricevendo strani comportamenti da qualche parte? –

+2

Nessun comportamento strano. Semplicemente curioso - stavo leggendo sul costruttore Integer (int i) - il punto che si è fatto era che il metodo statico Integer.valueOf (int i) potrebbe essere migliore dato che riutilizzerà gli oggetti come necessario - volevo controllare che fosse impossibile , non solo non convenzionale, per un costruttore per fare la cosa del riutilizzo. –

+8

Sì, è impossibile. In C++, è possibile sovrascrivere l'operatore 'new', ma non è possibile in Java. Il che non mi rende triste. –

risposta

16

L'operatore new assegna nuovo spazio heap e chiama il costruttore. Otterrai sempre un nuovo oggetto in questo modo (a meno che, come altri hanno sottolineato, venga generata un'eccezione nel costruttore).

La cosa è leggermente diversa con metodi statici che restituiscono un riferimento, ad esempio Integer.valueOf() che riutilizza gli oggetti da un pool interno, se possibile.

+1

Sì ed è anche uno schema consigliato nei grandi valori "Effective Java" –

6

Se il costruttore di Thing genera un'eccezione, l'oggetto non viene creato. Tuttavia, thing non punta mai a un'altra istanza esistente di Thing.

+0

di Joshua Bloch, né valori "null". È strano vedere il codice come 'Cosa t = nuova Cosa(); if (t == null) ... '- non accadrà mai –

0

No, nel caso non ci sia spazio in memoria per questo, si dovrebbe ottenere un OutOfMemoryError.

Ovviamente, potrebbero esserci altre eccezioni lanciate dal costruttore Thing.

+0

hmmm, perché non è un OutOfMemoryError? Solo interessato –

+0

l'eccezione corretta è in realtà OutOfMemoryError. – cd1

+0

@ CD1 @Tim Corretto l'errore. Sapevo che era qualcosa del genere. my bad –

0

Non sono sicuro di aver compreso correttamente la domanda.

La definizione di nuovo è per allocare e inizializzare un nuovo oggetto.

Immagino che potresti memorizzare un riferimento statico a un oggetto e quindi clonarlo per creare un nuovo oggetto, ma quell'oggetto sarebbe comunque nuovo.

Dato che non è possibile modificare il valore di this (altrimenti si potrebbe dire qualcosa come this = oldObject nel costruttore), l'unico modo per farlo è generare un'eccezione, come è stato menzionato prima.

0

per quanto ne so, non è come il C++ in cui è possibile sovraccaricare operator new o effettuare posizionamenti nuovi o altri oggetti allocatori. (ma non ho familiarità con JLS)

3

L'utilizzo di new genererà sempre un nuovo oggetto che viene allocato e creato. Tuttavia, si potrebbe fare riferimento al concetto di interning, dove gli oggetti e memorizzati in un pool e possono essere riutilizzati per risparmiare spazio. Per un buon esempio, vedere questo articolo su String interning in Java.

1

Il nuovo è sempre nuovo (con alcune eccezioni per i wrapper primitivi), ma se riutilizzare gli oggetti è un comportamento desiderato ci sono modi per farlo attraverso determinati schemi di progettazione (singleton, factory, pool ecc.).

+1

I wrapper primitivi (chiamati anche primitivi in ​​scatola) seguono le stesse regole di qualsiasi altra classe: se si utilizza un costruttore per crearne uno, si ottiene sempre una nuova istanza. Tuttavia, l'autoboxing non crea necessariamente un oggetto univoco ogni volta perché utilizza un metodo factory invece di un costruttore. –

+0

Ho detto qualcosa di diverso? – quosoo

+1

Nuovo è sempre nuovo. Non ci sono eccezioni, anche per i wrapper primitivi. – dave4420

-1

In Java, l'unica cosa che posso pensare è usare il pattern Singleton. Questo non creerebbe più nuove istanze di Thing, ma piuttosto un'istanza dello stesso oggetto ogni volta.

+1

Ogni volta che usi 'new', stai creando una nuova istanza. Periodo. Con il pattern Singleton, si chiama 'SingletonClass.getInstance()', non 'new SingletonClass()'. –

4

Diverse persone dicono che un oggetto non verrà creato se il costruttore genera un'eccezione. Vorrei solo sottolineare che questo non è vero.A titolo di esempio, dare un'occhiata a questo pessimo codice:

public class Test { 
    static int count; 

    static Set<Test> set = new HashSet<Test>(); 

    int id = count++; 


    public Test() { 
     set.add(this); 
     throw new RuntimeException(); 
    } 


    public static void main(String[] args) throws Exception { 
     for(int i = 0; i < 5; i++) { 
      try { 
       new Test(); 
      } catch(Exception e) { 
      } 
     } 
     System.out.println(set); 
    } 


    public String toString() { 
     return "Test[" + id + "]"; 
    } 
} 

L'output è:

[Test[0], Test[1], Test[2], Test[4], Test[3]] 

new crea un nuovo oggetto OGNI VOLTA.

0

new crea sempre un nuovo oggetto. In java non puoi riutilizzare l'oggetto usando new. In realtà questo porta a un problema di prestazioni in alcune classi Java. Ad es. La classe booleana può praticamente memorizzare solo due valori (true o false), tuttavia un utente può creare più oggetti con lo stesso valore utilizzando new.

0

No.

Dopo aver eseguito tale linea di codice thing sarà mai riferimento a un oggetto che esisteva prima linea.

0

La chiamata a new può non riuscire se è la prima volta che si fa riferimento alla classe e se la classe contiene blocchi statici che non riescono a inizializzarsi. Ho riscontrato comportamenti in cui eventuali errori di runtime che si verificano in un blocco o un costruttore statico comporteranno la nuova chiamata generando un'eccezione ClassNotFound nel contesto dell'utilizzo all'interno del server di applicazioni websphere. Il programma di caricamento classe websapparentemente respinge la classe dal caricamento a causa dell'eccezione di runtime.

Problemi correlati