Apa saja cara berbeda untuk membuat objek di Jawa?


178

Bercakap dengan rekan kerja kemarin tentang hal ini.

Ada yang jelas menggunakan konstruktor, tetapi apa cara lain di sana?


2
Jika ragu, lihat spesifikasi bahasa. 12.5 Pembuatan Instance Kelas Baru java.sun.com/docs/books/jls/third_edition/html/… 15.9 Ekspresi Pembuatan Instance Kelas java.sun.com/docs/books/jls/third_edition/html/…
Internet Friend

9
hanya ada 3: tor normal (kata kunci baru), klon () dan Unsafe.allocateInstance(Class). Sisanya memanggil salah satu dari mereka. Refleksi dikompilasi untuk panggilan c-tor, deserialization ke Unsafe.allocateInstance (Class). Anda dapat membuat API Anda sendiri dan pada akhirnya akan memanggil salah satunya.
bestsss

2
@ bestsss- Unsafeadalah detail khusus implementasi Java dan tidak disebutkan di mana pun dalam spesifikasi. Sangatlah mungkin untuk membangun sebuah implementasi Java compliant yang tidak menggunakan kompilasi refleksi ke kode yang menggunakan new, cloneatau Unsafe.allocateInstance.
templatetypedef


Jawaban:


288

Ada empat cara berbeda untuk membuat objek di java:

A . Menggunakan newkata kunci
Ini adalah cara paling umum untuk membuat objek di java. Hampir 99% objek dibuat dengan cara ini.

 MyObject object = new MyObject();

B . Menggunakan Class.forName()
Jika kita tahu nama kelas & jika memiliki konstruktor default publik kita dapat membuat objek dengan cara ini.

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

C . Menggunakan clone()
Klon () dapat digunakan untuk membuat salinan objek yang ada.

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

D . Menggunakan object deserialization
deserialisasi Obyek tidak lain adalah membuat objek dari bentuk serialnya.

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

Anda dapat membacanya dari sini .


10
Jadi sebenarnya hanya ada 2 cara: memanggil konstruktor (menggunakan yang baru, klon () atau refleksi) dan deserialisasi yang tidak memanggil konstruktor.
AlexR

13
@AlexR: Object.clone()tidak memanggil konstruktor juga.
axtavt

1
Karena ini sepertinya jawaban di atas, bisakah Anda menambahkan kreasi array sebagai sub-kasus ke A dan B? (Lihat jawaban saya untuk detail).
Paŭlo Ebermann

Deserialisation tidak memanggil konstruktor, hanya saja bukan tipe yang paling diturunkan.
Tom Hawtin - tackline

2
Anda juga harus menyebutkan Constructorkelas yang digeneralisasi Class.newInstance.
templatetypedef

68

Ada berbagai cara:

  • Melalui Class.newInstance.
  • Melalui Constructor.newInstance.
  • Melalui deserialisasi (menggunakan konstruktor no-args dari kelas dasar non-serialisable).
  • Melalui Object.clone( tidak memanggil konstruktor ).
  • Melalui JNI (harus memanggil konstruktor).
  • Melalui metode lain yang memanggil newAnda.
  • Saya kira Anda bisa menggambarkan pemuatan kelas sebagai membuat objek baru (seperti diinternir Strings).
  • Array literal sebagai bagian dari inisialisasi dalam deklarasi (tidak ada konstruktor untuk array).
  • Array dalam ...pemanggilan metode "varargs" ( ) (tidak ada konstruktor untuk array).
  • Rangkaian string konstan waktu non-kompilasi (kebetulan menghasilkan setidaknya empat objek, pada implementasi yang khas).
  • Menyebabkan eksepsi dibuat dan dilempar oleh runtime. Misalnya throw null;atau "".toCharArray()[0].
  • Oh, dan tinju primitif (kecuali di-cache), tentu saja.
  • JDK8 harus memiliki lambdas (dasarnya kelas batin anonim singkat), yang secara implisit dikonversi menjadi objek.
  • Untuk kelengkapan (dan Paŭlo Ebermann), ada beberapa sintaks dengan newkata kunci juga.

6
Anda harus menambahkan "cara normal", juga :-)
Paŭlo Ebermann

@ Paŭlo Ebermann Sekolah yang sangat tua dan tidak keren. (Saya berasumsi bahwa apa yang dimaksud dengan pertanyaan "gunakan konstruktor (meskipun sebagian besar, tetapi tidak semua, di atas menggunakan / konstruktor di suatu tempat di sepanjang garis).)
Tom Hawtin - tackline

sebenarnya hanya ada 3 cara nyata untuk melakukannya, yang saya tambahkan komentar
bestsss

3
Anda melewatkan satu: java.misc.Unsafe.allocateInstance(). Meskipun itu jahat karena sejumlah alasan. Dan sebenarnya, deserialisasi tidak menggunakan konstruktor no-args. Di bawah tenda itu menggunakan allocateInstancesihir hitam yang setara.
Stephen C

Jawaban terbaik, tetapi JNI AllocObject().tidak memanggil konstruktor.
Marquis of Lorne

25

Dalam bahasa Jawa, satu-satunya cara untuk membuat objek adalah dengan memanggil konstruktornya, baik secara eksplisit maupun implisit. Menggunakan hasil refleksi dalam panggilan ke metode konstruktor, deserialisasi menggunakan refleksi untuk memanggil konstruktor, metode pabrik membungkus panggilan ke konstruktor untuk abstrak konstruksi aktual dan kloning juga sama dengan panggilan konstruktor yang dibungkus.


1
Salah. Deserializatio tidak memanggil konstruktor kelas baik secara eksplisit maupun implisit.
Marquis of Lorne

2
Saya seharusnya tidak menulis 'konstruktornya' dan 'konstruktor', tetapi 'konstruktor' dan 'konstruktor'. Dalam kasus deserialisasi, konstruktor no-arg pertama yang berlaku selalu dipanggil.
Kebingungan

1
Implementasi klon default tidak memanggil konstruktor apa pun.
Didier L

jika ini adalah implementasi metode klon saya "return super.clone ();". Maka itu tidak akan memanggil konstruktor.
Mateen

13

Ya, Anda dapat membuat objek menggunakan refleksi. Misalnya, String.class.newInstance()akan memberi Anda objek String kosong baru.


1
jika saya menggunakan ini meminta saya untuk melampirkan di blok coba / tangkap.
GuruKulki

2
Ya, ada banyak kasus di mana pengecualian dapat dilemparkan. Lihat JavaDoc untuk newInstance () untuk contoh apa yang mungkin salah.
Thomas Lötzer

11

Ada lima cara berbeda untuk membuat objek di Jawa,

1. Menggunakan newkata kunci → konstruktor dipanggil

Employee emp1 = new Employee();

2. Menggunakan newInstance()metodeClass → constructor dipanggil

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

Dapat juga ditulis sebagai

Employee emp2 = Employee.class.newInstance();

3. Menggunakan newInstance()metodeConstructor → constructor dipanggil

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

4. Menggunakan clone()metode → tidak ada panggilan konstruktor

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

5. Menggunakan deserialisasi → tidak ada panggilan konstruktor

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

Tiga metode pertama newkata kunci dan keduanya newInstance()termasuk panggilan konstruktor tetapi kemudian dua metode kloning dan deserialisasi membuat objek tanpa memanggil konstruktor.

Semua metode di atas memiliki bytecode berbeda yang terkait dengannya, Baca berbagai cara untuk membuat objek di Java dengan Contoh untuk contoh dan deskripsi yang lebih terperinci misalnya konversi bytecode dari semua metode ini.

Namun orang dapat berargumen bahwa membuat objek array atau string juga merupakan cara untuk membuat objek tetapi hal-hal ini lebih spesifik untuk beberapa kelas saja dan ditangani langsung oleh JVM, sementara kita dapat membuat objek dari kelas apa saja dengan menggunakan 5 cara ini.


Harap ungkapkan afiliasi apa pun dan jangan gunakan situs sebagai cara untuk mempromosikan situs Anda melalui posting. Lihat Bagaimana cara menulis jawaban yang baik? .
Yvette



6

Ini harus diperhatikan jika Anda baru di java, setiap objek telah diwarisi dari Objek

Objek asli clone () melempar CloneNotSupportedException;


@stacker: Bisakah Anda jelaskan bagaimana ini terkait dengan membuat objek baru? Terima kasih.
ryanprayogo

4
@ryanprayogo clone () akan mengembalikan objek baru (walaupun objek tersebut adalah tiruan dari objek yang clone () dipanggil) dan sebenarnya satu-satunya cara untuk membuat objek baru tanpa konstruktor dipanggil.
Thomas Lötzer

6

Selain itu, Anda dapat menderialisasi data menjadi objek. Ini tidak melalui Konstruktor kelas!


DIPERBARUI : Terima kasih Tom karena menunjukkannya dalam komentar Anda! Dan Michael juga bereksperimen.

Ia melewati konstruktor dari superclass non-serializable yang paling banyak diturunkan.
Dan ketika kelas itu tidak memiliki konstruktor tanpa-args, InvalidClassException dilemparkan pada de-serialisasi.

Silakan lihat jawaban Tom untuk perawatan lengkap dari semua kasus ;-)
apakah ada cara lain untuk membuat objek tanpa menggunakan kata kunci "baru" di java


1
Itu pergi melalui konstruktor (konstruktor no-arg dari superclass non-serialisable paling banyak).
Tom Hawtin - tackline

1
@ Tom Oh wow - Saya tidak tahu itu dan sedikit bereksperimen. Rupanya ketika superclass non-serializable paling banyak tidak memiliki konstruktor no-args, itu menghasilkan InvalidClassException yang diserialisasi ke dalam aliran dan dilemparkan pada deserialisasi !! - Seberapa aneh itu?
Michael Borgwardt

6

Ada jenis objek, yang tidak dapat dibangun oleh mekanisme pembuatan instance normal (memanggil konstruktor): Array . Array dibuat dengan

 A[] array = new A[len];

atau

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

Seperti yang dikatakan Sean dalam komentar, ini secara sintaksis mirip dengan panggilan konstruktor dan secara internal tidak lebih dari alokasi dan nol-inisialisasi (atau menginisialisasi dengan konten eksplisit, dalam kasus kedua) blok memori, dengan beberapa header untuk menunjukkan jenis dan panjangnya.

Ketika meneruskan argumen ke metode-varargs, sebuah array juga dibuat (dan diisi) secara implisit.

Cara keempat adalah

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

Tentu saja, kloning dan deserialisasi juga berlaku di sini.

Ada banyak metode dalam API Standar yang membuat array, tetapi semuanya sebenarnya menggunakan satu (atau lebih) cara ini.


Memang, Anda tidak dapat menentukan konstruktor Array, tetapi selain itu mekanismenya adalah newkata kunci yang sama . Array.newInstance adalah satu-satunya mekanisme baru di sini
Sean Patrick Floyd

@Sean: Ini kata kunci yang sama, tetapi ini merupakan mekanisme internal yang sangat berbeda, saya berani mengatakan.
Paŭlo Ebermann

Itu benar, tentu saja. Tetapi di sisi lain versi penciptaan array yang berbeda secara internal hampir sama. Baru menyadari jawaban Anda dari tahun 2011. Maaf untuk mengaduk barang-barang lama :-)
Sean Patrick Floyd

@Sean: Tidak masalah, saya menggunakan kesempatan ini untuk melakukan perbaikan tata bahasa.
Paŭlo Ebermann

kerja bagus, tidak ada yang membahas di sini tentang array!
Mateen

5

Cara lain jika kita bersikap menyeluruh.

  • Pada Oracle JVM adalah Unsafe.allocateInstance () yang membuat instance tanpa memanggil konstruktor.
  • Menggunakan manipulasi kode byte Anda dapat menambahkan kode untuk anewarray, multianewarray, newarrayatau new. Ini dapat ditambahkan menggunakan perpustakaan seperti ASM atau BCEL. Versi bcel dikirimkan dengan Java Oracle. Sekali lagi ini tidak memanggil konstruktor, tetapi Anda dapat memanggil konstruktor sebagai panggilan terpisah.


4

Refleksi juga akan melakukan pekerjaan untuk Anda.

SomeClass anObj = SomeClass.class.newInstance();

adalah cara lain untuk membuat instance baru dari sebuah kelas. Dalam hal ini, Anda juga harus menangani pengecualian yang mungkin dilemparkan.


4
  • menggunakan newoperator (dengan demikian memanggil konstruktor)
  • menggunakan refleksi clazz.newInstance()(yang lagi-lagi memanggil konstruktor). Atau dengan clazz.getConstructor(..).newInstance(..)(lagi menggunakan konstruktor, tetapi Anda dapat memilih yang mana)

Untuk meringkas jawaban - satu cara utama - dengan memanggil konstruktor dari kelas objek.

Pembaruan: Jawaban lain mencantumkan dua cara yang tidak melibatkan penggunaan konstruktor - desentralisasi dan kloning.


4

Ada LIMA cara berbeda untuk membuat objek di Jawa:

1. Menggunakan kata kunci `baru`:

Ini adalah cara paling umum untuk membuat objek di Jawa. Hampir 99% objek dibuat dengan cara ini.

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

2. Dengan Menggunakan Metode Pabrik:

ClassName ObgRef=ClassName.FactoryMethod();

Contoh:

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

3. Dengan Menggunakan Konsep Kloning:

Dengan menggunakan clone(), clone()dapat digunakan untuk membuat salinan dari objek yang ada.

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

4. Menggunakan `Class.forName ()`:

Jika kita tahu nama kelasnya & jika memiliki konstruktor default publik, kita dapat membuat objek dengan cara ini.

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

Contoh:

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

5. Menggunakan deserialisasi objek:

Deserialisasi objek tidak lain adalah membuat objek dari bentuk serialnya.

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

(4) hanya mengharuskan Class.forName()jika Anda belum memiliki kelas, yang dalam semua kasus lain Anda lakukan. Itu juga tidak memerlukan konstruktor no-args: ada cara untuk memanggil konstruktor publik apa pun jika Anda tahu argumen yang benar. Dan Anda telah meninggalkan setidaknya dua cara lain.
Marquis of Lorne

2
(2) Metode Pabrik hanyalah pola untuk mendapatkan objek. Tetapi secara internal ia menggunakan kata kunci "baru" untuk membuat objek.
Karthik Bose

Bung mengapa begitu banyak orang mengatakan metode pabrik membuat objek, dari mana kalian belajar ini?
Mateen

3

Anda juga dapat mengkloning objek yang sudah ada (jika mengimplementasikan Cloneable).

Foo fooClone = fooOriginal.clone (); 

2

Metode 1

Menggunakan kata kunci baru. Ini adalah cara paling umum untuk membuat objek di java. Hampir 99% objek dibuat dengan cara ini.

Employee object = new Employee();

Metode 2

Menggunakan Class.forName (). Class.forName () memberi Anda objek kelas, yang berguna untuk refleksi. Metode yang dimiliki objek ini ditentukan oleh Java, bukan oleh programmer yang menulis kelas. Mereka sama untuk setiap kelas. Memanggil newInstance () pada yang memberikan Anda sebuah instance dari kelas itu (yaitu callingClass.forName ("ExampleClass"). NewInstance () itu sama dengan memanggil ExampleClass baru ()), di mana Anda dapat memanggil metode yang didefinisikan oleh kelas, mengakses bidang yang terlihat dll.

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

Class.forName () akan selalu menggunakan ClassLoader dari pemanggil, sedangkan ClassLoader.loadClass () dapat menentukan ClassLoader yang berbeda. Saya percaya bahwa Class.forName menginisialisasi kelas yang dimuat juga, sedangkan pendekatan ClassLoader.loadClass () tidak langsung melakukannya (itu tidak diinisialisasi sampai digunakan untuk pertama kalinya).

Yang lain harus membaca:

Java: Thread State Pendahuluan dengan Contoh Simple Java Enum Example

Metode 3

Menggunakan clone (). Klon () dapat digunakan untuk membuat salinan dari objek yang ada.

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

Metode 4

Menggunakan metode newInstance ()

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

Metode 5

Menggunakan Deserialisasi Objek. Deserialisasi Objek tidak lain adalah membuat objek dari bentuk serialnya.

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

Jangan gunakan pemformatan kode untuk teks yang bukan kode. Ada lebih banyak metode dari ini. Baca jawaban lainnya. 'Hampir 99%' hanyalah dugaan.
Marquis of Lorne

Hai EJP maaf atas kesalahan ini ... Saya mengatakan ini adalah salah satu cara untuk membuat objek tidak mengatakan dengan tepat itu yang benar. Ini hanya model..dan maaf saya sudah tahu dan yang baru ke stackoverflow
Andriya

0

Dari perspektif pengguna API, alternatif lain untuk konstruktor adalah metode pabrik statis (seperti BigInteger.valueOf ()), meskipun untuk pembuat API (dan secara teknis "nyata") objek masih dibuat menggunakan konstruktor.


-1

Tergantung persis apa yang Anda maksud dengan membuat tetapi beberapa yang lain adalah:

  • Metode klon
  • Deserialisasi
  • Reflection (Class.newInstance ())
  • Reflection (objek konstruktor)

2
3 dan 4 adalah alias yang berbeda untuk mekanisme yang sama
Sean Patrick Floyd

-2

ada juga ClassLoader.loadClass (string) tetapi ini tidak sering digunakan.

dan jika Anda ingin menjadi pengacara total tentang hal itu, array adalah teknis objek karena properti .length array. jadi menginisialisasi array menciptakan sebuah objek.


1
loadClass (Nama string) mengembalikan objek Kelas yang dihasilkan suatu objek ya Tapi tidak objek kelas itu. Jika contoh diberikan maka kita dapat menemukan banyak contoh seperti itu di seluruh perpustakaan java tetapi mereka akan spesifik kelas. periksa youtu.be/gGGCmrD6Qpw
nanosoft

-3

Kita dapat membuat objek dalam 5 cara:

  1. oleh operator baru
  2. oleh refleksi (mis. Class.forName () diikuti oleh Class.newInstance ())
  3. dengan metode pabrik
  4. dengan kloning
  5. oleh api refleksi

3
Class.forName () memuat kelas daripada membuat objek.
Marquis of Lorne

refleksi? Tentunya yang Anda maksud refleksi.
Stephen C

bagaimana Anda membuat objek dari metode pabrik, implementasi internal mungkin lagi menggunakan kata kunci baru kan? dan mengapa Anda memiliki refleksi dua kali? Akan lebih masuk akal jika Anda benar-benar memberikan beberapa contoh
Mateen

-5

Kami juga dapat membuat objek dengan cara ini: -

String s ="Hello";

Tidak ada yang membahasnya.


Ini adalah cara membuat tipe data primitif, ini hanya fleksibilitas yang disediakan Java di belakang layar untuk tidak menggunakan kata kunci "baru". Ini sama dengan kata kunci baru.
Madusudanan

Madhusudan, FYI, Dengan bantuan operator baru, objek harus selalu disimpan dalam tumpukan sementara dalam hal ini "Halo" adalah objek yang harus disimpan dalam string pool. Dan String adalah kelas bukan tipe data primitif.
Deepak Sharma

Ini tidak membuat objek. Ini memberikan referensi ke objek yang ada. Objek sudah dibuat oleh kompiler dan classloader.
Marquis of Lorne
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.