Quali sono tutti i diversi modi per creare un oggetto in Java?


178

L'altro giorno ho avuto una conversazione con un collega.

C'è l'ovvio usando un costruttore, ma quali sono gli altri modi lì?


2
In caso di dubbi, guarda le specifiche della lingua. 12.5 Creazione di nuove istanze di classe java.sun.com/docs/books/jls/third_edition/html/… 15.9 Espressioni sulla creazione di istanze di classe java.sun.com/docs/books/jls/third_edition/html/…
Internet Friend

9
ce ne sono solo 3: c-tor normale (nuova parola chiave), clone () e Unsafe.allocateInstance(Class). Il resto chiama uno di quelli. Reflection viene compilato per chiamare il c-tor, deserializzazione in Unsafe.allocateInstance (Class). Puoi creare la tua API e finirai per chiamarne una.
bestsss

2
@ bestsss- Unsafeè un dettaglio specifico dell'implementazione di Java e non è menzionato da nessuna parte nelle specifiche. E 'del tutto possibile costruire un'implementazione Java compatibile che non fa uso di compilazione riflessione verso il basso per il codice che utilizza new, cloneo Unsafe.allocateInstance.
templatetypedef


Risposte:


288

Esistono quattro modi diversi per creare oggetti in Java:

A . Uso della newparola chiave
Questo è il modo più comune per creare un oggetto in Java. Quasi il 99% degli oggetti viene creato in questo modo.

 MyObject object = new MyObject();

B . Utilizzo Class.forName()
Se conosciamo il nome della classe e se ha un costruttore predefinito pubblico, possiamo creare un oggetto in questo modo.

MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();

C . Usando clone()
Il clone () può essere usato per creare una copia di un oggetto esistente.

MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();

D . L'uso della object deserialization
deserializzazione di oggetti non è altro che la creazione di un oggetto dalla sua forma serializzata.

ObjectInputStream inStream = new ObjectInputStream(anInputStream );
MyObject object = (MyObject) inStream.readObject();

Puoi leggerli da qui .


10
Quindi in realtà esistono solo 2 modi: chiamare il costruttore (usando new, clone () o reflection) e la deserializzazione che non invoca il costruttore.
AlexR

13
@AlexR: Object.clone()non invoca anche il costruttore.
axtavt,

1
Poiché questa sembra essere la risposta in alto, potresti aggiungere le creazioni di array come sotto-casi ad A e B? (Vedi la mia risposta per i dettagli).
Paŭlo Ebermann,

La deserializzazione invoca un costruttore, ma non del tipo più derivato.
Tom Hawtin - tackline il

2
Dovresti anche menzionare la Constructorclasse, che generalizza Class.newInstance.
templatetypedef

68

Esistono vari modi:

  • Attraverso Class.newInstance.
  • Attraverso Constructor.newInstance.
  • Attraverso la deserializzazione (usa il costruttore no-args della classe base non sierializzabile più derivata).
  • Attraverso Object.clone( non chiama un costruttore ).
  • Attraverso JNI (dovrebbe chiamare un costruttore).
  • Attraverso qualsiasi altro metodo che chiama a newper te.
  • Immagino che potresti descrivere il caricamento della classe come creazione di nuovi oggetti (come interned String).
  • Un array letterale come parte dell'inizializzazione in una dichiarazione (nessun costruttore per gli array).
  • La matrice in una ...chiamata del metodo "varargs" ( ) (nessun costruttore per le matrici).
  • Concatenazione di stringhe costanti di tempo non compilabili (produce almeno quattro oggetti, in un'implementazione tipica).
  • Causare un'eccezione da creare e generare dal runtime. Ad esempio throw null;o "".toCharArray()[0].
  • Oh, e la boxe dei primitivi (a meno che non sia memorizzata nella cache), ovviamente.
  • JDK8 dovrebbe avere lambda (essenzialmente classi interne anonime concise), che vengono convertite implicitamente in oggetti.
  • Per completezza (e Paŭlo Ebermann), c'è anche una sintassi con la newparola chiave.

6
Dovresti aggiungere anche il "modo normale" :-)
Paŭlo Ebermann,

@ Paŭlo Ebermann È così vecchia scuola e rara. (Supponevo che ciò che la domanda intendesse per "usare un costruttore (sebbene la maggior parte, ma non tutti, di quanto sopra utilizzi il / un costruttore da qualche parte lungo la linea).)
Tom Hawtin - affronta il

in realtà ci sono solo 3 modi reali per farlo, per il quale ho aggiunto un commento
bestsss

3
Ti sei perso uno: java.misc.Unsafe.allocateInstance(). Anche se è brutto per una serie di motivi. E in realtà, la deserializzazione non usa il costruttore no-args. Sotto il cofano usa allocateInstanceuna magia nera equivalente.
Stephen C,

La migliore risposta ancora, ma JNI AllocObject().non chiama un costruttore.
Marchese di Lorne,

25

All'interno del linguaggio Java, l'unico modo per creare un oggetto è chiamare il suo costruttore, sia esplicitamente che implicitamente. Usando la riflessione si ottiene una chiamata al metodo del costruttore, la deserializzazione usa la riflessione per chiamare il costruttore, i metodi di fabbrica avvolgono la chiamata al costruttore per astrarre la costruzione effettiva e la clonazione è allo stesso modo una chiamata del costruttore chiusa.


1
Non corretto. Deserializatio non chiama il costruttore di una classe né esplicitamente né implicitamente.
Marchese di Lorne,

2
Non avrei dovuto scrivere "il suo costruttore" e "il costruttore", ma piuttosto "un costruttore" e "un costruttore". Nel caso della deserializzazione, viene sempre chiamato il primo costruttore no-arg applicabile.
Confusione,

1
L'implementazione clone predefinita non chiama alcun costruttore.
Didier L

se questa è l'implementazione del mio metodo clone "return super.clone ();". Quindi non invocherà il costruttore.
Mateen,

13

Sì, puoi creare oggetti usando la riflessione. Ad esempio, String.class.newInstance()ti darà un nuovo oggetto String vuoto.


1
se lo uso mi sta chiedendo di racchiuderlo in un blocco try / catch.
GuruKulki,

2
Sì, ci sono molti casi in cui è possibile generare eccezioni. Vedi JavaDoc per newInstance () per esempi di cosa potrebbe andare storto.
Thomas Lötzer,

11

Esistono cinque modi diversi per creare un oggetto in Java,

1. Usando la newparola chiave → costruttore viene chiamato

Employee emp1 = new Employee();

2. Utilizzando il newInstance()metodo diClass → costruttore viene chiamato

Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
                                .newInstance();

Può anche essere scritto come

Employee emp2 = Employee.class.newInstance();

3. Utilizzando il newInstance()metodo diConstructor → costruttore viene chiamato

Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();

4. Utilizzo del clone()metodo → nessuna chiamata del costruttore

Employee emp4 = (Employee) emp3.clone();

5. Utilizzo della deserializzazione → nessuna chiamata del costruttore

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();

Le prime tre newparole chiave dei metodi ed entrambe newInstance()includono una chiamata del costruttore, ma in seguito due metodi di clonazione e deserializzazione creano oggetti senza chiamare il costruttore.

Tutti i suddetti metodi hanno diversi bytecode associati, Leggi Diversi modi per creare oggetti in Java con esempi per esempi e descrizioni più dettagliate, ad es. Conversione bytecode di tutti questi metodi.

Tuttavia, si può sostenere che la creazione di un oggetto array o stringa è anche un modo per creare l'oggetto, ma queste cose sono più specifiche solo per alcune classi e gestite direttamente da JVM, mentre possiamo creare un oggetto di qualsiasi classe utilizzando questi 5 modi.


Si prega di rivelare eventuali affiliazioni e non utilizzare il sito come mezzo per promuovere il proprio sito attraverso la pubblicazione. Vedi Come posso scrivere una buona risposta? .
Yvette,



6

Questo dovrebbe essere notato se sei nuovo a Java, ogni oggetto ha ereditato da Object

il clone Object protetto nativo () genera CloneNotSupportedException;


@stacker: Potresti spiegare in che modo ciò è legato alla creazione di un nuovo oggetto? Grazie.
ryanprayogo,

4
@ryanprayogo clone () restituirà un nuovo oggetto (anche se l'oggetto è un clone dell'oggetto su cui è stato chiamato clone ()) ed è in realtà l'unico modo per creare un nuovo oggetto senza che venga chiamato il costruttore.
Thomas Lötzer,

6

Inoltre, è possibile deserializzare i dati in un oggetto. Questo non passa attraverso il costruttore di classe!


AGGIORNATO : Grazie Tom per averlo sottolineato nel tuo commento! E anche Michael ha sperimentato.

Passa attraverso il costruttore della superclasse non serializzabile più derivata.
E quando quella classe non ha un costruttore no-args, viene lanciata una InvalidClassException al momento della deserializzazione.

Si prega di consultare la risposta di Tom per un trattamento completo di tutti i casi ;-)
Esiste un altro modo per creare un oggetto senza utilizzare la "nuova" parola chiave in Java


1
Passa attraverso un costruttore (il costruttore no-arg della superclasse non sierializzabile più derivata).
Tom Hawtin: affronta il

1
@Tom Oh wow - non lo sapevo e ho sperimentato un po '. Apparentemente quando la superclasse non serializzabile più derivata non ha un costruttore no-args, si traduce in una invalidClassException serializzata nel flusso e generata in fase di deserializzazione !! - Quanto è bizzarro?
Michael Borgwardt,

6

Esiste un tipo di oggetto, che non può essere costruito dai normali meccanismi di creazione dell'istanza (chiamando costruttori): Array . Le matrici vengono create con

 A[] array = new A[len];

o

 A[] array = new A[] { value0, value1, value2 };

Come ha detto Sean in un commento, questo è sintatticamente simile a una chiamata del costruttore e internamente non è molto più che allocazione e inizializzazione zero (o inizializzazione con contenuto esplicito, nel secondo caso) un blocco di memoria, con qualche intestazione per indicare il digitare e la lunghezza.

Quando si passano argomenti a un metodo varargs, viene creato (e riempito) implicitamente anche un array.

Un quarto modo sarebbe

 A[] array = (A[]) Array.newInstance(A.class, len);

Naturalmente, anche qui la clonazione e la deserializzazione funzionano.

Esistono molti metodi nell'API standard che creano array, ma in realtà tutti usano uno (o più) di questi modi.


Certo, non è possibile definire i costruttori di array, ma a parte questo il meccanismo è la stessa newparola chiave. Array.newInstance è l'unico nuovo meccanismo qui
Sean Patrick Floyd il

@Sean: è la stessa parola chiave, ma è un meccanismo interno piuttosto diverso, oserei dire.
Paŭlo Ebermann,

È vero, certo. D'altra parte, le diverse versioni della creazione dell'array sono praticamente le stesse all'interno. Ho appena realizzato che la tua risposta è stata del 2011. Scusa per aver rimescolato roba vecchia :-)
Sean Patrick Floyd,

@Sean: nessun problema, ho usato questa occasione per fare qualche correzione grammaticale.
Paŭlo Ebermann,

bel lavoro, nessuno ha discusso qui sugli array!
Mateen,

5

Altri modi se siamo esaustivi.

  • In Oracle JVM è Unsafe.allocateInstance () che crea un'istanza senza chiamare un costruttore.
  • Utilizzando manipolazione bytecode è possibile aggiungere il codice a anewarray, multianewarray, newarrayo new. Questi possono essere aggiunti usando librerie come ASM o BCEL. Una versione di bcel viene fornita con Oracle Java. Ancora una volta questo non chiama un costruttore, ma puoi chiamarlo come una chiamata separata.


4

La riflessione farà anche il lavoro per te.

SomeClass anObj = SomeClass.class.newInstance();

è un altro modo per creare una nuova istanza di una classe. In questo caso, dovrai anche gestire le eccezioni che potrebbero essere generate.


4
  • usando l' newoperatore (invocando così un costruttore)
  • usando la riflessione clazz.newInstance()(che invoca nuovamente il costruttore). Oppure clazz.getConstructor(..).newInstance(..)(usando nuovamente un costruttore, ma puoi scegliere quale)

Riassumendo la risposta - un modo principale - invocando il costruttore della classe dell'oggetto.

Aggiornamento: un'altra risposta ha elencato due modi che non comportano l'uso di un costruttore: deseralizzazione e clonazione.


4

Esistono CINQUE modi diversi per creare oggetti in Java:

1. Usando la parola chiave `new`:

Questo è il modo più comune per creare un oggetto in Java. Quasi il 99% degli oggetti viene creato in questo modo.

MyObject object = new MyObject();//normal way

2. Utilizzando il metodo di fabbrica:

ClassName ObgRef=ClassName.FactoryMethod();

Esempio:

RunTime rt=Runtime.getRunTime();//Static Factory Method

3. Usando il concetto di clonazione:

Usando clone(), clone()può essere usato per creare una copia di un oggetto esistente.

MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object

4. Utilizzando `Class.forName ()`:

Se conosciamo il nome della classe e se ha un costruttore predefinito pubblico, possiamo creare un oggetto in questo modo.

MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();

Esempio:

String st=(String)Class.forName("java.lang.String").newInstance();

5. Utilizzo della deserializzazione degli oggetti:

La deserializzazione degli oggetti non è altro che la creazione di un oggetto dalla sua forma serializzata.

ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();

(4) richiede solo Class.forName()se non hai già la classe, cosa che in tutti gli altri casi hai. Inoltre non richiede un costruttore no-args: ci sono modi per chiamare qualsiasi costruttore pubblico se si conoscono gli argomenti corretti. E hai lasciato fuori almeno altri due modi.
Marchese di Lorne,

2
(2) Metodo di fabbrica è solo un modello per ottenere oggetti. Ma internamente utilizza la "nuova" parola chiave per creare oggetti.
Karthik Bose,

amico, perché così tante persone dicono che il metodo factory crea oggetti, da dove lo avete imparato?
Mateen,

3

Puoi anche clonare oggetti esistenti (se implementa Cloneable).

Foo fooClone = fooOriginal.clone (); 

2

Metodo 1

Utilizzando una nuova parola chiave. Questo è il modo più comune per creare un oggetto in Java. Quasi il 99% degli oggetti viene creato in questo modo.

Employee object = new Employee();

Metodo 2

Utilizzando Class.forName (). Class.forName () ti dà l'oggetto di classe, che è utile per la riflessione. I metodi che ha questo oggetto sono definiti da Java, non dal programmatore che scrive la classe. Sono gli stessi per ogni classe. Chiamare newInstance () su che ti dà un'istanza di quella classe (es. CallingClass.forName ("ExampleClass"). NewInstance () equivale a chiamare new ExampleClass ()), su cui puoi chiamare i metodi che la classe definisce, accedere ai campi visibili ecc.

Employee object2 = (Employee) Class.forName(NewEmployee).newInstance();

Class.forName () utilizzerà sempre ClassLoader del chiamante, mentre ClassLoader.loadClass () può specificare un ClassLoader diverso. Credo che Class.forName inizializzi anche la classe caricata, mentre l'approccio ClassLoader.loadClass () non lo fa immediatamente (non è inizializzato fino a quando non viene usato per la prima volta).

Un altro deve leggere:

Java: Introduzione allo stato del thread con esempio Esempio di Enum Java semplice

Metodo 3

Usando clone (). Il clone () può essere utilizzato per creare una copia di un oggetto esistente.

Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();

Metodo 4

Utilizzando il metodo newInstance ()

Object object4 = Employee.class.getClassLoader().loadClass(NewEmployee).newInstance();

Metodo 5

Utilizzo della deserializzazione degli oggetti. La deserializzazione di oggetti non è altro che la creazione di un oggetto dalla sua forma serializzata.

// Create Object5
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("");
ObjectOutputStream oout = new ObjectOutputStream(out);

// write something in the file
oout.writeObject(object3);
oout.flush();

// create an ObjectInputStream for the file we created before
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("crunchify.txt"));
Employee object5 = (Employee) ois.readObject();

Non utilizzare la formattazione del codice per il testo che non è codice. Esistono più metodi di questi. Leggi le altre risposte. "Quasi il 99%" è solo un'ipotesi.
Marchese di Lorne,

Ciao EJP mi dispiace per questo errore ... Ho detto che questo è un tipo di modo per creare gli oggetti non detto esattamente è quello giusto. È solo un modello..e scusa sono uno studente e uno nuovo da
impilare

0

Dal punto di vista dell'utente API, un'altra alternativa ai costruttori sono i metodi factory statici (come BigInteger.valueOf ()), anche se per l'autore dell'API (e tecnicamente "per davvero") gli oggetti vengono comunque creati usando un costruttore.


-1

Dipende esattamente cosa intendi per creare, ma alcuni altri sono:

  • Metodo di clonazione
  • deserializzazione
  • Reflection (Class.newInstance ())
  • Riflessione (oggetto costruttore)

2
3 e 4 sono alias diversi per lo stesso meccanismo
Sean Patrick Floyd il

-2

c'è anche ClassLoader.loadClass (stringa) ma questo non è spesso usato.

e se vuoi essere un vero avvocato al riguardo, gli array sono tecnicamente oggetti a causa della proprietà .length di un array. l'inizializzazione di un array crea quindi un oggetto.


1
loadClass (String name) restituisce l'oggetto Class risultante che un oggetto sì Ma non l'oggetto di quella classe. Se vengono forniti esempi, è possibile trovare numerosi esempi simili nella libreria java, ma quelli saranno specifici della classe. check youtu.be/gGGCmrD6Qpw
nanosoft

-3

Possiamo creare un oggetto in 5 modi:

  1. dal nuovo operatore
  2. per riflessione (ad es. Class.forName () seguito da Class.newInstance ())
  3. con il metodo di fabbrica
  4. clonando
  5. per riflessione api

3
Class.forName () carica una classe anziché creare un oggetto.
Marchese di Lorne,

riflessione? Sicuramente vuoi dire riflessione.
Stephen C,

come creeresti l'oggetto dal metodo factory, l'implementazione interna potrebbe essere di nuovo usando la nuova parola chiave giusto? e perché hai la riflessione due volte? Sarebbe più sensato se davvero dessi alcuni esempi
Mateen,

-5

Possiamo anche creare l'oggetto in questo modo: -

String s ="Hello";

Nessuno ne ha discusso.


Questo è il modo di creare tipi di dati primitivi, è solo una flessibilità che Java offre dietro le quinte per non usare la "nuova" parola chiave. È la stessa della nuova parola chiave.
Madusudanan,

Madhusudan, FYI, Con l'aiuto di un nuovo operatore, gli oggetti dovrebbero sempre essere archiviati in heap mentre in questo caso "Hello" è un oggetto che dovrebbe essere archiviato nel pool di stringhe. E String è una classe non un tipo di dati primitivo.
Deepak Sharma,

Questo non crea un oggetto. Assegna un riferimento a un oggetto esistente. L'oggetto era già stato creato dal compilatore e dal classloader.
Marchese di Lorne,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.