web-dev-qa-db-ja.com

Javaでオブジェクトを作成するためのさまざまな方法は何ですか?

先日、これについて同僚と会話しました。

明らかなコンストラクタの使い方がありますが、他の方法は何ですか?

168
Mike Deck

Javaでオブジェクトを作成する方法は4つあります。

Anewキーワードを使用する
これは、Javaでオブジェクトを作成するための最も一般的な方法です。このようにして、ほぼ99%のオブジェクトが作成されます。

 MyObject object = new MyObject();

BClass.forName()を使う
クラスの名前がわかっていて、それにパブリックのデフォルトコンストラクタがある場合は、この方法でオブジェクトを作成できます。

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

Cclone()を使う
clone()を使って既存のオブジェクトのコピーを作成することができます。

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

Dobject deserializationを使う
オブジェクトの逆シリアル化は、直列化された形式からオブジェクトを作成することに他なりません。

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

こちら から読むことができます。

276
kamaci

さまざまな方法があります。

  • Class.newInstanceを通じて。
  • Constructor.newInstanceを通じて。
  • 逆シリアル化を介して(最も派生した直列化不可能な基本クラスの引数なしのコンストラクタを使用します)。
  • Object.cloneを通して(コンストラクターを呼び出さない)。
  • JNIを介して(コンストラクターを呼び出す必要があります)。
  • あなたのためにnewを呼び出す他のメソッドを通して。
  • クラスローディングは新しいオブジェクトを作成するものとして説明できると思います(内部のStringsなど)。
  • 宣言内の初期化の一部としてのリテラル配列(配列用のコンストラクタはありません)。
  • "varargs"(...)メソッド呼び出し内の配列(配列用のコンストラクタはありません)。
  • コンパイル時定数以外の文字列連結(通常の実装では、少なくとも4つのオブジェクトが生成されます)。
  • ランタイムによって作成およびスローされる例外を引き起こします。例えばthrow null;"".toCharArray()[0]です。
  • ああ、そして(キャッシュされていない限り)プリミティブのボクシング、もちろん。
  • JDK 8には、暗黙的にオブジェクトに変換されるラムダ(基本的には簡潔な匿名内部クラス)があります。
  • 完全を期すため(そしてPaŭloEbermann)、newキーワードを使った構文もあります。
66

Java言語の中では、オブジェクトを作成する唯一の方法は、そのコンストラクターを呼び出すことです(明示的または暗黙的)。リフレクションを使用してコンストラクタメソッドを呼び出すと、デシリアライゼーションはリフレクションを使用してコンストラクタを呼び出します。ファクトリメソッドはコンストラクタへの呼び出しをラップして実際のコンストラクションを抽象化し、クローン作成も同様にラップされたコンストラクタコールです。

25
Confusion

はい、反射を使ってオブジェクトを作成できます。例えばString.class.newInstance()はあなたに新しい空のStringオブジェクトを与えます。

13
Thomas Lötzer

Javaでオブジェクトを作成する方法は5つあります。

1。 newname__キーワードを使用する→コンストラクタが呼び出される

Employee emp1 = new Employee();

2。 ClassnameのnewInstance()メソッドを使う__→コンストラクタが呼ばれる

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

次のように書くこともできます。

Employee emp2 = Employee.class.newInstance();

3。 ConstructornameのnewInstance()メソッドを使う__→コンストラクタが呼ばれる

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

4。 clone()メソッドを使用する→コンストラクタを呼び出さない

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

5。逆シリアル化を使用する→コンストラクタ呼び出しなし

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

最初の3つのメソッドnewname__キーワードと両方のnewInstance()はコンストラクター呼び出しを含みますが、後の2つのcloneメソッドと逆シリアル化メソッドはコンストラクターを呼び出さずにオブジェクトを作成します。

上記のすべてのメソッドには、それぞれ異なるバイトコードが関連付けられています。Read 例および/詳細な説明については、例 を使用してJavaでオブジェクトを作成する方法は異なります。これらすべてのメソッドのバイトコード変換.

しかし、配列または文字列オブジェクトを作成することもオブジェクトを作成する方法であると主張できますが、これらのことはクラスによってのみ特定され、JVMによって直接処理されます。

10
Naresh Joshi
9
Bill the Lizard

通常のインスタンス作成メカニズム(コンストラクタを呼び出す)では構築できないオブジェクトの種類があります。配列。配列はで作成されます

 A[] array = new A[len];

または

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

Seanがコメントで述べたように、これは構文的にはコンストラクタ呼び出しと似ており、内部的には割り当てとゼロ初期化(または明示的な内容で初期化すること、後者の場合)を意味します。種類と長さ。

引数をvarargsメソッドに渡すと、配列も暗黙のうちに作成され(そして埋められ)ます。

4番目の方法は

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

もちろん、クローン作成と逆シリアル化もここで機能します。

標準APIには配列を作成するメソッドがたくさんありますが、実際にはこれらのメソッドのうちの1つ(または複数)を使用しています。

6
Paŭlo Ebermann

また使用することができます

 Object myObj = Class.forName("your.cClass").newInstance();
6

あなたがJavaに不慣れであるならば、これは注意されるべきです、すべてのオブジェクトはObjectから継承しました

保護されたネイティブのObject clone()はCloneNotSupportedExceptionをスローします。

6
stacker

また、データをオブジェクトにデシリアライズすることもできます。これはコンストラクタクラスを通らない!


UPDATED:あなたのコメントでそれを指摘してくれてありがとうTomそしてマイケルも実験した。

最も派生しているシリアライズ不可能なスーパークラスのコンストラクタを通過します。
そして、そのクラスに引数のないコンストラクタがない場合、直列化復元時にInvalidClassExceptionがスローされます。

トムの答えを見て、すべてのケースを完全に処理してください;-)
Javaで "new"キーワードを使わずにオブジェクトを作成する方法は他にもあります

6
KLE

私たちが徹底的であるならば他の方法。

  • Oracle JVMには、コンストラクタを呼び出さずにインスタンスを作成するUnsafe.allocateInstance()があります。
  • バイトコード操作を使用して、anewarraymultianewarraynewarray、またはnewにコードを追加できます。これらは、ASMやBCELなどのライブラリを使用して追加できます。あるバージョンのbcelがOracleのJavaに同梱されています。これもコンストラクタを呼び出しませんが、コンストラクタを別々の呼び出しとして呼び出すことができます。
5
Peter Lawrey

反射もあなたのために仕事をするでしょう。

SomeClass anObj = SomeClass.class.newInstance();

クラスの新しいインスタンスを作成する別の方法です。この場合は、スローされる可能性のある例外も処理する必要があります。

4
ryanprayogo
  • new演算子を使用する(したがってコンストラクタを呼び出す)
  • リフレクションclazz.newInstance()を使用します(これもコンストラクタを呼び出します)。あるいはclazz.getConstructor(..).newInstance(..)によって(やはりコンストラクタを使用しますが、あなたはどちらを選択することができます)

オブジェクトクラスのコンストラクタを呼び出すことで、答えを要約することができます。これは主な方法の1つです。

更新:別の回答では、コンストラクタを使用しない2つの方法がリストされています。

4
Bozho

反射:

someClass.newInstance();
4
John Meagher

既存のオブジェクトのクローンを作成することもできます(それがクローン可能を実装している場合)。

Foo fooClone = fooOriginal.clone (); 
3
Roman

Javaでオブジェクトを作成する方法は5つあります。

1. `new`キーワードを使う:

これは、Javaでオブジェクトを作成するための最も一般的な方法です。このようにして、ほぼ99%のオブジェクトが作成されます。

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

2.ファクトリーメソッドを使用して

ClassName ObgRef=ClassName.FactoryMethod();

例:

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

3.クローニングの概念を使用して

clone()を使用することによって、clone()を使用して既存のオブジェクトのコピーを作成することができます。

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

4. `Class.forName()`を使う:

クラスの名前がわかっていて、それにパブリックのデフォルトコンストラクタがある場合は、この方法でオブジェクトを作成できます。

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

例:

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

5.オブジェクトの直列化復元を使用します。

オブジェクトの逆シリアル化は、シリアル化された形式からオブジェクトを作成することに他なりません。

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

方法1

新しいキーワードを使用しています。これは、Javaでオブジェクトを作成するための最も一般的な方法です。このようにして、ほぼ99%のオブジェクトが作成されます。

Employee object = new Employee();

方法2

Class.forName()を使用します。 Class.forName()はクラスオブジェクトを返します。これはリフレクションに役立ちます。このオブジェクトが持つメソッドは、クラスを書いているプログラマによってではなく、Javaによって定義されます。それらはすべてのクラスで同じです。その上でnewInstance()を呼び出すと、そのクラスのインスタンスが得られます(つまり、callingClass.forName( "ExampleClass")。newInstance()は、new ExampleClass()を呼び出すのと同じことになり、クラスで定義されているメソッドを呼び出すことができます)。可視フィールドなどにアクセスする.

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

Class.forName()は常に呼び出し元のClassLoaderを使用しますが、ClassLoader.loadClass()は別のClassLoaderを指定できます。 Class.forNameはロードされたクラスも初期化しますが、ClassLoader.loadClass()アプローチはすぐには初期化しません(初めて使用されるまで初期化されません)。

別の人は読む必要があります:

Java:例による単純なJava Enumの例によるスレッド状態の紹介

方法3

Clone()を使用してください。 clone()を使って既存のオブジェクトのコピーを作成することができます。

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

方法4

NewInstance()メソッドを使用する

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

方法5

オブジェクトの逆シリアル化を使用するオブジェクトの逆シリアル化は、直列化された形式からオブジェクトを作成することに他なりません。

// 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();
2
Andriya

APIユーザーの観点からは、コンストラクタの代わりに静的なファクトリメソッド(BigInteger.valueOf()など)を使用することもできますが、APIの作成者(および厳密には「for for」)では、オブジェクトはコンストラクタを使用して作成されます。

0
Fabian Steeg