Java'da bir sınıfı isme göre başlatmanın bir yolu var mı?


102

Şu soruyu arıyordum: Bir sınıfın ismine sahipken nasıl başlatılacağını açıklayan dizge adından bir sınıfı örnekleyin . Java'da yapmanın bir yolu var mı? Paket adına ve sınıf adına sahip olacağım ve bu belirli ada sahip bir nesne oluşturabilmem gerekiyor.


Biz örneğini bir sınıf ve sonucu, bir nesne (veya: örneği ).
Andreas Dolk

1
Cevap evet, ama ben sormak gerektiğini düşünüyorum eğer onun iyi bir fikir. Büyük güç (yansıma) büyük sorumluluk getirir ve onu yalnızca sonuçlarını anlarsanız ve düşündüyseniz kullanmalısınız.
c1moore

Yanıtlar:


239

İki yol:

Yöntem 1 - yalnızca bağımsız değişken oluşturucu içermeyen sınıflar için

Sınıfınızda bağımsız değişken olmayan bir kurucu varsa, bir örnek oluşturmak için yöntemi Classkullanarak bir nesne edinebilir Class.forName()ve kullanabilirsiniz newInstance()(bununla birlikte, bu yöntemin Java'nın kontrol edilen istisnalarını yenebileceği için genellikle kötü olarak kabul edildiğine dikkat edin ).

Örneğin:

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

Yöntem 2

Sınıfın arginsiz oluşturucuları yoksa da işe yarayan daha güvenli bir alternatif yaklaşım, Constructornesnesini almak için sınıf nesnenizi sorgulamak ve newInstance()bu nesnede bir yöntem çağırmaktır :

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

Her iki yöntem de yansıma olarak bilinir . Aşağıdakiler dahil olmak üzere, genellikle meydana gelebilecek çeşitli istisnaları yakalamanız gerekecektir:

  • JVM sınıfınızı bulamıyor veya yükleyemiyor
  • başlatmaya çalıştığınız sınıfın doğru tür kurucuları yok
  • yapıcının kendisi bir istisna attı
  • çağırmaya çalıştığınız kurucu herkese açık değil
  • bir güvenlik yöneticisi kuruldu ve yansımanın oluşmasını engelliyor

merhaba, nesneyi bir kez yarattıktan sonra newInstance(), onu kendi nesnemize geri çevirebilir miyiz?
GMsoF

@Simon, güvenlik yöneticisi hakkında detaylandırabilir / bilgi verebilir misiniz?
Ram

Bunu anlamıyorum Başka bir dizindeki bilinmeyen bir dosyadaki bir sınıfa erişmek istiyorum, dizge olarak yalnızca yolun / dosyanın adına sahibim. "Dir / unkonwn.java" dizesi. Class.forName ("dir / unknown") çağırmak bana hata veriyor.
john ktejik

Nasıl yayın yapabiliyorsa instanceiçin com.foo.MyClass? göz önüne alındığında com.foo.MyClass sadece bir dizedir
Sanket9394

14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();

15
Sınıfın parametresiz yapıcısı yoksa (ve başka oluşturucuları varsa) veya parametresiz kurucu erişilemezse bunun işe yaramayacağını belirtmek gerekir.
Dawood ibn Kareem

3

Kullanım Class.forName ( "Sınıf String adı") newInstance (.);

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

Bu, A adlı sınıfın başlatılmasına neden olur.


Başına paket adı eklenmiş olsa bile benim için çalışmıyor. :(
trusktr

3

Kullanarak bir örnek oluşturmak için bir sınıfın tam nitelikli adını almayı kolaylaştırmak için Class.forName(...), Class.getName()yöntem kullanılabilir. Gibi bir şey:

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;
    }
}

Daha sonra, geçtiğiniz sınıfa geri döndüğünüz nesneyi çevirebilirsiniz makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);

1
Sadece Yapamam clazz.newInstance()yerine getNameo fromName?
user276648

1

Java yansımasını kullan

Yeni Nesnelerin Yaratılması Yapıcılar için yöntem çağırmaya eşdeğer bir şey yoktur, çünkü bir kurucuyu çağırmak yeni bir nesne yaratmaya eşdeğerdir (en kesin olmak gerekirse, yeni bir nesne oluşturmak hem bellek ayırmayı hem de nesne oluşturmayı içerir). Dolayısıyla, önceki örneğe en yakın eşdeğer şunu söylemektir:

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);
         }
      }
   }

nesnenin yeni bir örneğini oluşturmak için belirtilen parametre türlerini işleyen ve onu çağıran bir yapıcı bulur. Bu yaklaşımın değeri, derleme zamanında değil, yürütme zamanında yapıcı araması ve çağırma ile tamamen dinamik olmasıdır.



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

0

bunun gibi bir şey çalışmalı ...

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

0

newInstance()Doğrudan kullanmak Java 8'den itibaren kullanımdan kaldırılmıştır Class.getDeclaredConstructor(...).newInstance(...). İlgili istisnalarla kullanmanız gerekir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.