C'è un modo per istanziare una classe in base al nome in Java?


102

Stavo cercando come la domanda: istanzia una classe dal suo nome di stringa che descrive come istanziare una classe quando ha il suo nome. C'è un modo per farlo in Java? Avrò il nome del pacchetto e il nome della classe e devo essere in grado di creare un oggetto con quel nome particolare.


Abbiamo istanziato una classe e il risultato è un oggetto (o: esempio ).
Andreas Dolk

1
La risposta è sì, ma penso che dovresti chiedere se è una buona idea. Da un grande potere (riflessione) derivano grandi responsabilità e dovresti usarlo solo se capisci e hai considerato le conseguenze.
c1moore

Risposte:


239

Due strade:

Metodo 1: solo per classi che hanno un costruttore senza argomenti

Se la tua classe ha un costruttore senza argomenti, puoi ottenere un Classoggetto usando Class.forName()e utilizzare il newInstance()metodo per creare un'istanza (anche se fai attenzione che questo metodo è spesso considerato malvagio perché può sconfiggere le eccezioni controllate di Java).

Per esempio:

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

Metodo 2

Un approccio alternativo più sicuro che funziona anche se la classe non ha costruttori no-arg è interrogare il tuo oggetto di classe per ottenere il suo Constructoroggetto e chiamare un newInstance()metodo su questo oggetto:

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

Entrambi i metodi sono noti come riflessione . In genere dovrai rilevare le varie eccezioni che possono verificarsi, incluse cose come:

  • la JVM non riesce a trovare o non riesce a caricare la tua classe
  • la classe che stai cercando di istanziare non ha il giusto tipo di costruttori
  • il costruttore stesso ha lanciato un'eccezione
  • il costruttore che stai cercando di invocare non è pubblico
  • è stato installato un gestore della sicurezza che impedisce la riflessione

ciao, una volta che abbiamo creato l'oggetto da newInstance(), potremmo restituirlo al nostro oggetto?
GMsoF

@ Simon puoi elaborare / fornire un suggerimento sul responsabile della sicurezza?
Ram

Non lo capisco. Voglio accedere a una classe in un file sconosciuto in un'altra directory, ho solo il nome del percorso / file come stringa. Stringa "dir / unkonwn.java". La chiamata a Class.forName ("dir / unknown") mi dà degli errori.
john ktejik,

Come possiamo lanciare instancea com.foo.MyClass? dato che com.foo.MyClass è solo una stringa
Sanket9394

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

15
Vale la pena ricordare che questo non funziona se la classe non ha un costruttore senza parametri (e ha altri costruttori), o se il costruttore senza parametri è inaccessibile.
Dawood ibn Kareem

3

use Class.forName ("String name of class"). newInstance ();

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

Ciò causerà l'inizializzazione della classe A.


Non funziona per me, anche con il nome del pacchetto anteposto. :(
trusktr

3

Per rendere più facile ottenere il nome completo di una classe per creare un'istanza utilizzando Class.forName(...), si potrebbe utilizzare il Class.getName()metodo. Qualcosa di simile a:

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

Quindi puoi eseguire il cast dell'oggetto che torni a qualsiasi classe a cui passi makeObject(...):

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

1
Non puoi semplicemente clazz.newInstance()invece di getNameallora fromName?
user276648

1

Usa la riflessione Java

Creazione di nuovi oggetti Non esiste alcun equivalente alla chiamata di metodo per i costruttori, perché invocare un costruttore equivale a creare un nuovo oggetto (per essere più precisi, la creazione di un nuovo oggetto implica sia l'allocazione della memoria che la costruzione dell'oggetto). Quindi l'equivalente più vicino all'esempio precedente è dire:

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

che trova un costruttore che gestisce i tipi di parametro specificati e lo invoca, per creare una nuova istanza dell'oggetto. Il valore di questo approccio è che è puramente dinamico, con la ricerca e il richiamo del costruttore al momento dell'esecuzione, piuttosto che al momento della compilazione.



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

0

qualcosa del genere dovrebbe funzionare ...

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

0

L'utilizzo newInstance()diretto è deprecato a partire da Java 8. È necessario utilizzare Class.getDeclaredConstructor(...).newInstance(...)con le eccezioni corrispondenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.