Apakah ada cara untuk membuat instance kelas berdasarkan nama di Java?

102

Saya melihat sebagai pertanyaan: Membuat instance kelas dari nama stringnya yang menjelaskan cara membuat instance kelas saat memiliki namanya. Apakah ada cara untuk melakukannya di Java? Saya akan memiliki nama paket dan nama kelas dan saya harus dapat membuat objek yang memiliki nama khusus itu.

ict1991
sumber
Kami instantiate sebuah kelas dan hasilnya adalah sebuah objek (atau: misalnya ).
Andreas Dolk
1
Jawabannya adalah ya, tapi saya rasa Anda harus bertanya apakah itu ide yang bagus. Dengan kekuatan yang besar (refleksi) datanglah tanggung jawab yang besar dan Anda sebaiknya hanya menggunakannya jika Anda memahami dan telah mempertimbangkan konsekuensinya.
c1lebih lanjut

Jawaban:

239

Dua arah:

Metode 1 - hanya untuk kelas yang memiliki konstruktor tanpa argumen

Jika kelas Anda memiliki konstruktor no-arg, Anda bisa mendapatkan Classobjek menggunakan Class.forName()dan menggunakan newInstance()metode untuk membuat instance (meskipun berhati-hatilah karena metode ini sering dianggap jahat karena dapat mengalahkan pengecualian yang dicentang dari Java).

Sebagai contoh:

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

Metode 2

Pendekatan alternatif yang lebih aman yang juga berfungsi jika kelas tidak memiliki konstruktor no-arg adalah dengan membuat kueri objek kelas Anda untuk mendapatkan Constructorobjeknya dan memanggil newInstance()metode pada objek ini:

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

Kedua metode tersebut dikenal sebagai refleksi . Anda biasanya harus mengetahui berbagai pengecualian yang dapat terjadi, termasuk hal-hal seperti:

  • JVM tidak dapat menemukan atau tidak dapat memuat kelas Anda
  • kelas yang Anda coba buat tidak memiliki jenis konstruktor yang tepat
  • konstruktor itu sendiri memberikan pengecualian
  • konstruktor yang Anda coba panggil tidak bersifat publik
  • manajer keamanan telah diinstal dan mencegah terjadinya refleksi
Simon Nickerson
sumber
hai, setelah kita membuat objek dari newInstance(), dapatkah kita mengembalikannya ke objek kita sendiri?
GMsoF
@Simon Bisakah Anda menjelaskan / memberikan petunjuk tentang manajer keamanan?
Ram
Saya tidak mengerti ini. Saya ingin mengakses kelas dalam file yang tidak dikenal di beberapa direktori lain, saya hanya memiliki nama jalur / file sebagai string. String "dir / unkonwn.java". Memanggil Class.forName ("dir / unknown") memberi saya kesalahan.
john ktejik
Bagaimana kita dapat melemparkan instanceke com.foo.MyClass? mengingat bahwa com.foo.MyClass hanyalah sebuah string
Sanket9394
14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
scibuff
sumber
15
Perlu disebutkan bahwa ini tidak berfungsi jika kelas tidak memiliki konstruktor tanpa parameter (dan memiliki konstruktor lain), atau jika konstruktor tanpa parameter tidak dapat diakses.
Dawood ibn Kareem
3

gunakan Class.forName ("Nama string kelas"). newInstance ();

Class.forName("A").newInstance();

Ini akan menyebabkan kelas bernama A diinisialisasi.

Chandra Sekhar
sumber
Tidak berfungsi untuk saya, bahkan dengan nama paket diawali. :(
trusktr
3

Untuk membuatnya lebih mudah mendapatkan nama kelas yang sepenuhnya memenuhi syarat untuk membuat instance menggunakan Class.forName(...), seseorang dapat menggunakan Class.getName()metode ini. Sesuatu seperti:

class ObjectMaker {
    // Constructor, fields, initialization, etc...
    public Object makeObject(Class<?> clazz) {
        Object o = null;

        try {
            o = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            // There may be other exceptions to throw here, 
            // but I'm writing this from memory.
            e.printStackTrace();
        }

        return o;
    }
}

Kemudian Anda dapat mentransmisikan objek yang Anda dapatkan kembali ke kelas mana pun yang Anda teruskan makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);
Roberto
sumber
1
Tidak bisa Anda hanya clazz.newInstance()bukan getNameitu fromName?
pengguna276648
1

Gunakan refleksi java

Membuat Objek Baru Tidak ada ekuivalen dengan pemanggilan metode untuk konstruktor, karena pemanggilan konstruktor sama dengan membuat objek baru (untuk lebih tepatnya, membuat objek baru melibatkan alokasi memori dan konstruksi objek). Jadi persamaan terdekat dengan contoh sebelumnya adalah dengan mengatakan:

import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

yang menemukan konstruktor yang menangani tipe parameter yang ditentukan dan memanggilnya, untuk membuat instance baru dari objek. Nilai dari pendekatan ini adalah bahwa itu murni dinamis, dengan pencarian dan pemanggilan konstruktor pada waktu eksekusi, bukan pada waktu kompilasi.

kornero
sumber
1

Class.forName ("ClassName") akan menyelesaikan tujuan Anda.

Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
Balaswamy Vaddeman
sumber
0
String str = (String)Class.forName("java.lang.String").newInstance();
Chen Harel
sumber
0

sesuatu seperti ini seharusnya bekerja ...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();
Shashank Kadne
sumber
0

Menggunakan newInstance()secara langsung sudah tidak digunakan lagi pada Java 8. Anda perlu menggunakan Class.getDeclaredConstructor(...).newInstance(...)dengan pengecualian yang sesuai.

Mel
sumber