Quelles sont les différentes manières de créer un objet en Java?

178

J'ai eu une conversation avec un collègue l'autre jour à ce sujet.

Il y a l'évidence d'utiliser un constructeur, mais quelles sont les autres façons?

Mike Deck
la source
2
En cas de doute, regardez les spécifications de la langue. 12.5 Création de nouvelles instances de classe java.sun.com/docs/books/jls/third_edition/html/… 15.9 Expressions de création d'instance de classe java.sun.com/docs/books/jls/third_edition/html/…
Internet Friend
9
il n'y en a que 3: c-tor normal (nouveau mot-clé), clone () et Unsafe.allocateInstance(Class). Les autres appellent l'un de ceux-là. La réflexion est compilée en appel c-tor, la désérialisation en Unsafe.allocateInstance (Class). Vous pouvez créer votre propre API et vous finirez par appeler l'une d'entre elles.
bestsss
2
@ bestsss- Unsafeest un détail spécifique à l'implémentation de Java et n'est mentionné nulle part dans la spécification. Il est tout à fait possible de construire une implémentation Java compatible qui n'utilise pas vers le bas de réflexion à la compilation du code qui utilise new, cloneou Unsafe.allocateInstance.
templatetypedef
2
vous pouvez vérifier le lien, codesandlogics.com/2017/01/ways-to-create-objects-in-java.html
Pragya

Réponses:

288

Il existe quatre façons différentes de créer des objets en java:

A . Utilisation du newmot-clé
C'est la manière la plus courante de créer un objet en java. Près de 99% des objets sont créés de cette manière.

 MyObject object = new MyObject();

B . En utilisant Class.forName()
Si nous connaissons le nom de la classe et si elle a un constructeur par défaut public, nous pouvons créer un objet de cette manière.

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

C . clone()
L' utilisation de The clone () peut être utilisée pour créer une copie d'un objet existant.

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

D . Utiliser la object deserialization
désérialisation d'objet n'est rien d'autre que créer un objet à partir de sa forme sérialisée.

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

Vous pouvez les lire ici .

Kamaci
la source
10
Donc, en fait, il n'existe que 2 façons: appeler le constructeur (en utilisant new, clone () ou la réflexion) et la désérialisation qui n'appelle pas le constructeur.
AlexR
13
@AlexR: Object.clone()n'invoque pas non plus le constructeur.
axtavt
1
Comme cela semble être la réponse en haut, pourriez-vous ajouter les créations de tableaux en tant que sous-cas à A et B? (Voir ma réponse pour plus de détails).
Paŭlo Ebermann le
La désérialisation appelle un constructeur, mais pas du type le plus dérivé.
Tom Hawtin - tackline
2
Vous devez également mentionner la Constructorclasse, qui généralise Class.newInstance.
templatetypedef
68

Il existe différentes manières:

  • À travers Class.newInstance.
  • À travers Constructor.newInstance.
  • Par la désérialisation (utilise le constructeur no-args de la classe de base non sérialisable la plus dérivée).
  • Through Object.clone( n'appelle pas de constructeur ).
  • Via JNI (devrait appeler un constructeur).
  • Par toute autre méthode qui appelle un newpour vous.
  • Je suppose que vous pourriez décrire le chargement de classe comme la création de nouveaux objets (tels que des internés String).
  • Un tableau littéral faisant partie de l'initialisation dans une déclaration (pas de constructeur pour les tableaux).
  • Le tableau dans un ...appel de méthode "varargs" ( ) (pas de constructeur pour les tableaux).
  • Concaténation de chaînes à constante de temps non compilée (produit au moins quatre objets, sur une implémentation typique).
  • Provoque la création et la levée d'une exception par le runtime. Par exemple throw null;ou "".toCharArray()[0].
  • Oh, et la boxe des primitifs (sauf en cas de cache), bien sûr.
  • JDK8 doit avoir des lambdas (classes internes anonymes essentiellement concises), qui sont implicitement converties en objets.
  • Pour être complet (et Paŭlo Ebermann), il existe également une syntaxe avec le newmot - clé.
Tom Hawtin - Tacle
la source
6
Vous devriez aussi ajouter la "voie normale" :-)
Paŭlo Ebermann
@ Paŭlo Ebermann C'est tellement vieille école et pas cool. (J'ai supposé que ce que signifiait la question par "utiliser un constructeur (bien que la plupart des éléments ci-dessus, mais pas tous, utilisent le constructeur / a quelque part le long de la ligne).)
Tom Hawtin - tackline
en fait, il n'y a que 3 vraies façons de le faire, pour lesquelles j'ai ajouté un commentaire
bestsss
3
Vous avez manqué un: java.misc.Unsafe.allocateInstance(). Bien que ce soit désagréable pour un certain nombre de raisons. Et en fait, la désérialisation n'utilise pas le constructeur no-args. Sous le capot, il utilise allocateInstanceou équivalent de la magie noire.
Stephen C
Meilleure réponse encore, mais JNI AllocObject().n'appelle pas de constructeur.
Marquis of Lorne
25

Dans le langage Java, la seule façon de créer un objet est d'appeler son constructeur, que ce soit explicitement ou implicitement. L'utilisation de la réflexion entraîne un appel à la méthode du constructeur, la désérialisation utilise la réflexion pour appeler le constructeur, les méthodes de fabrique encapsulent l'appel au constructeur pour faire abstraction de la construction réelle et le clonage est de la même manière un appel de constructeur encapsulé.

Confusion
la source
1
Incorrect. Deserializatio n'appelle pas le constructeur d'une classe explicitement ou implicitement.
Marquis of Lorne
2
Je n'aurais pas dû écrire «son constructeur» et «le constructeur», mais plutôt «un constructeur» et «un constructeur». Dans le cas de la désérialisation, le premier constructeur no-arg applicable est toujours appelé.
Confusion
1
L'implémentation de clonage par défaut n'appelle aucun constructeur.
Didier L
si c'est mon implémentation de méthode de clonage "return super.clone ();". Ensuite, il n'appellera pas le constructeur.
Mateen
13

Oui, vous pouvez créer des objets en utilisant la réflexion. Par exemple, String.class.newInstance()vous donnera un nouvel objet String vide.

Thomas Lötzer
la source
1
si j'utilise cela, il me demande de l'inclure dans un bloc try / catch.
GuruKulki
2
Oui, il existe de nombreux cas où des exceptions peuvent être levées. Voir le JavaDoc pour newInstance () pour des exemples de ce qui pourrait mal tourner.
Thomas Lötzer
11

Il existe cinq façons différentes de créer un objet en Java,

1. En utilisant le newmot-clé → le constructeur est appelé

Employee emp1 = new Employee();

2. En utilisant la newInstance()méthode deClass → le constructeur est appelé

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

Il peut également être écrit comme

Employee emp2 = Employee.class.newInstance();

3. En utilisant la newInstance()méthode deConstructor → le constructeur est appelé

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

4. Utilisation de la clone()méthode → aucun appel de constructeur

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

5. Utilisation de la désérialisation → pas d'appel au constructeur

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

Les trois premiers newmots-clés de méthodes et les deux newInstance()incluent un appel au constructeur, mais plus tard, deux méthodes de clonage et de désérialisation créent des objets sans appeler le constructeur.

Toutes les méthodes ci-dessus ont différents bytecode qui leur sont associés, Lire Différentes façons de créer des objets en Java avec exemple pour des exemples et une description plus détaillée, par exemple la conversion de bytecode de toutes ces méthodes.

Cependant, on peut affirmer que la création d'un objet tableau ou chaîne est également un moyen de créer l'objet, mais ces choses sont plus spécifiques à certaines classes uniquement et gérées directement par JVM, alors que nous pouvons créer un objet de n'importe quelle classe en utilisant ces 5 méthodes.

Naresh Joshi
la source
Veuillez divulguer toute affiliation et ne pas utiliser le site comme un moyen de promouvoir votre site par la publication. Voir Comment rédiger une bonne réponse? .
Yvette
6

Vous pouvez également utiliser

 Object myObj = Class.forName("your.cClass").newInstance();
Vincent Ramdhanie
la source
6

Cela doit être remarqué si vous êtes nouveau sur Java, chaque objet a hérité d'Object

Protégé native Object clone () lance CloneNotSupportedException;

empileur
la source
@stacker: Pouvez-vous expliquer en quoi cela est lié à la création d'un nouvel objet? Merci.
ryanprayogo
4
@ryanprayogo clone () retournera un nouvel objet (même si l'objet est un clone de l'objet sur lequel clone () a été appelé) et est en fait le seul moyen de créer un nouvel objet sans que le constructeur ne soit appelé.
Thomas Lötzer
6

En outre, vous pouvez désérialiser les données dans un objet. Cela ne passe pas par la classe Constructor!


MISE À JOUR : Merci Tom d'avoir souligné cela dans votre commentaire! Et Michael a également expérimenté.

Il passe par le constructeur de la superclasse non sérialisable la plus dérivée.
Et lorsque cette classe n'a pas de constructeur no-args, une exception InvalidClassException est lancée lors de la désérialisation.

S'il vous plaît voir la réponse de Tom pour un traitement complet de tous les cas ;-)
existe-t-il un autre moyen de créer un objet sans utiliser le mot clé "new" en java

KLE
la source
1
Il passe par un constructeur (le constructeur sans argument de la superclasse non sérialisable la plus dérivée).
Tom Hawtin - tackline
1
@Tom Oh wow - Je ne savais pas cela et j'ai expérimenté un peu. Apparemment, lorsque la superclasse non sérialisable la plus dérivée n'a pas de constructeur no-args, il en résulte qu'une InvalidClassException est sérialisée dans le flux et lancée lors de la désérialisation !! - Est-ce que c'est bizarre?
Michael Borgwardt
6

Il existe un type d'objet, qui ne peut pas être construit par des mécanismes de création d'instances normaux (appelant des constructeurs): tableaux . Les tableaux sont créés avec

 A[] array = new A[len];

ou

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

Comme Sean l'a dit dans un commentaire, c'est syntaxiquement similaire à un appel de constructeur et en interne ce n'est pas beaucoup plus que l'allocation et l'initialisation à zéro (ou l'initialisation avec un contenu explicite, dans le second cas) un bloc de mémoire, avec un en-tête pour indiquer le le type et la longueur.

Lorsque vous passez des arguments à une méthode varargs, un tableau est également créé (et rempli) implicitement.

Une quatrième façon serait

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

Bien sûr, le clonage et la désérialisation fonctionnent ici aussi.

Il existe de nombreuses méthodes dans l'API standard qui créent des tableaux, mais elles utilisent toutes en fait une (ou plusieurs) de ces méthodes.

Paŭlo Ebermann
la source
Certes, vous ne pouvez pas définir de constructeurs Array, mais à part cela, le mécanisme est le même newmot-clé. Array.newInstance est le seul nouveau mécanisme ici
Sean Patrick Floyd
@Sean: C'est le même mot-clé, mais c'est un mécanisme interne assez différent, j'ose dire.
Paŭlo Ebermann
C'est vrai, bien sûr. Mais d'un autre côté, les différentes versions de la création de tableaux sont sensiblement les mêmes en interne. Je viens de réaliser que votre réponse datait de 2011. Désolé d'avoir remué de vieux trucs :-)
Sean Patrick Floyd
@Sean: Pas de problème, j'ai profité de cette occasion pour faire quelques corrections de grammaire.
Paŭlo Ebermann
beau travail, personne n'a discuté ici des tableaux!
Mateen
5

D'autres moyens si nous sommes exhaustifs.

  • Sur Oracle JVM, Unsafe.allocateInstance () crée une instance sans appeler de constructeur.
  • En utilisant la manipulation de code octet , vous pouvez ajouter du code à anewarray, multianewarray, newarrayou new. Ceux-ci peuvent être ajoutés à l'aide de bibliothèques telles que ASM ou BCEL. Une version de bcel est livrée avec Java d'Oracle. Encore une fois, cela n'appelle pas de constructeur, mais vous pouvez appeler un constructeur en tant qu'appel séparé.
Peter Lawrey
la source
4

Réflexion:

someClass.newInstance();
John Meagher
la source
4

La réflexion fera également le travail pour vous.

SomeClass anObj = SomeClass.class.newInstance();

est une autre façon de créer une nouvelle instance d'une classe. Dans ce cas, vous devrez également gérer les exceptions susceptibles d'être levées.

ryanprayogo
la source
4
  • en utilisant l' newopérateur (invoquant ainsi un constructeur)
  • en utilisant la réflexion clazz.newInstance()(qui appelle à nouveau le constructeur). Ou par clazz.getConstructor(..).newInstance(..)(à nouveau en utilisant un constructeur, mais vous pouvez donc choisir lequel)

Pour résumer la réponse - une manière principale - en invoquant le constructeur de la classe de l'objet.

Mise à jour: Une autre réponse a répertorié deux méthodes qui n'impliquent pas l'utilisation d'un constructeur: la déséralisation et le clonage.

Bozho
la source
4

Il existe CINQ façons différentes de créer des objets en Java:

1. Utilisation du mot-clé «new»:

C'est la manière la plus courante de créer un objet en Java. Près de 99% des objets sont créés de cette manière.

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

2. En utilisant la méthode d'usine:

ClassName ObgRef=ClassName.FactoryMethod();

Exemple:

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

3. En utilisant le concept de clonage:

En utilisant clone(), le clone()peut être utilisé pour créer une copie d'un objet existant.

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

4. En utilisant `Class.forName ()`:

Si nous connaissons le nom de la classe et si elle a un constructeur par défaut public, nous pouvons créer un objet de cette manière.

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

Exemple:

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

5. Utilisation de la désérialisation d'objet:

La désérialisation d'objet n'est rien d'autre que la création d'un objet à partir de sa forme sérialisée.

ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();
KVSubrahmanya Reddy
la source
(4) ne nécessite que Class.forName()si vous n'avez pas déjà la classe, ce que vous faites dans tous les autres cas. Il ne nécessite pas non plus de constructeur sans args: il existe des moyens d'appeler n'importe quel constructeur public si vous connaissez les bons arguments. Et vous avez omis au moins deux autres moyens.
Marquis de Lorne
2
(2) La méthode d'usine est juste un modèle pour obtenir des objets. Mais en interne, il utilise un mot-clé "nouveau" pour créer des objets.
Karthik Bose
mec pourquoi tant de gens disent que la méthode d'usine crée des objets, d'où avez-vous appris cela?
Mateen
3

Vous pouvez également cloner un objet existant (s'il implémente Cloneable).

Foo fooClone = fooOriginal.clone (); 
romain
la source
2

Méthode 1

Utilisation d'un nouveau mot-clé. C'est la manière la plus courante de créer un objet en java. Près de 99% des objets sont créés de cette manière.

Employee object = new Employee();

Méthode 2

Utilisation de Class.forName (). Class.forName () vous donne l'objet de classe, ce qui est utile pour la réflexion. Les méthodes de cet objet sont définies par Java, pas par le programmeur qui écrit la classe. Ils sont les mêmes pour chaque classe. L'appel de newInstance () sur qui vous donne une instance de cette classe (c'est-à-dire callClass.forName ("ExampleClass"). NewInstance () équivaut à appeler new ExampleClass ()), sur lequel vous pouvez appeler les méthodes que la classe définit, accéder aux champs visibles etc.

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

Class.forName () utilisera toujours le ClassLoader de l'appelant, tandis que ClassLoader.loadClass () peut spécifier un ClassLoader différent. Je crois que Class.forName initialise également la classe chargée, alors que l'approche ClassLoader.loadClass () ne le fait pas tout de suite (elle n'est initialisée que lorsqu'elle est utilisée pour la première fois).

Un autre doit lire:

Java: Introduction à l'état des threads avec un exemple Exemple simple d'énumération Java

Méthode 3

Utilisation de clone (). Le clone () peut être utilisé pour créer une copie d'un objet existant.

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

Méthode 4

Utilisation de la méthode newInstance ()

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

Méthode 5

Utilisation de la désérialisation d'objets. La désérialisation d'objet n'est rien d'autre que la création d'un objet à partir de sa forme sérialisée.

// 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();
Andriya
la source
N'utilisez pas de formatage de code pour du texte qui n'est pas du code. Il existe plus de méthodes que celles-ci. Lisez les autres réponses. «Presque 99%» n'est que supposition.
Marquis of Lorne
Salut EJP désolé pour cette erreur ... J'ai dit que c'est un moyen de créer les objets qui ne sont pas exactement dits, c'est juste un modèle ... et je suis désolé je suis un apprenant et un nouveau à stackoverflow
Andriya
0

Du point de vue de l'utilisateur de l'API, une autre alternative aux constructeurs sont les méthodes de fabrique statiques (comme BigInteger.valueOf ()), bien que pour l'auteur de l'API (et techniquement "pour de vrai") les objets soient toujours créés à l'aide d'un constructeur.

Fabian Steeg
la source
-1

Cela dépend exactement de ce que vous entendez par créer, mais d'autres sont:

  • Méthode de clonage
  • Désérialisation
  • Réflexion (Class.newInstance ())
  • Reflection (objet Constructor)
Garth Gilmour
la source
2
3 et 4 sont des alias différents pour le même mécanisme
Sean Patrick Floyd
-2

il y a aussi ClassLoader.loadClass (string) mais ce n'est pas souvent utilisé.

et si vous voulez être un avocat total à ce sujet, les tableaux sont techniquement des objets en raison de la propriété .length d'un tableau. donc l'initialisation d'un tableau crée un objet.

Randy L
la source
1
loadClass (String name) renvoie l'objet de classe résultant qui est un objet oui Mais pas l'objet de cette classe. Si des exemples sont donnés, nous pouvons en trouver de nombreux dans la bibliothèque java, mais ceux-ci seront spécifiques à la classe. consultez youtu.be/gGGCmrD6Qpw
nanosoft
-3

Nous pouvons créer un objet de 5 manières:

  1. par nouvel opérateur
  2. par réflexion (par exemple Class.forName () suivi de Class.newInstance ())
  3. par méthode d'usine
  4. par clonage
  5. par reflet api
tanushree roy
la source
3
Class.forName () charge une classe plutôt que de créer un objet.
Marquis de Lorne
réflexion? Vous voulez sûrement dire réflexion.
Stephen C
comment créeriez-vous un objet à partir de la méthode d'usine, l'implémentation interne peut être à nouveau en utilisant un nouveau mot clé, non? et pourquoi réfléchissez-vous deux fois? Cela aurait plus de sens si vous donniez réellement quelques exemples
Mateen
-5

Nous pouvons également créer l'objet de cette manière: -

String s ="Hello";

Personne n'en a discuté.

Deepak Sharma
la source
C'est la manière de créer des types de données primitifs, c'est juste une flexibilité que Java fournit en arrière-plan pour ne pas utiliser le mot-clé "new". C'est la même chose que le mot-clé new.
Madusudanan
Madhusudan, FYI, Avec l'aide d'un nouvel opérateur, les objets doivent toujours être stockés en tas alors que dans ce cas "Hello" est un objet qui doit stocker dans le pool String. Et String est une classe et non un type de données primitif.
Deepak Sharma
Cela ne crée pas d'objet. Il attribue une référence à un objet existant. L'objet avait déjà été créé par le compilateur et le chargeur de classe.
Marquis of Lorne