Есть ли способ создать экземпляр класса по имени в Java?

103

Я смотрел как вопрос: создать экземпляр класса из его строкового имени, которое описывает, как создать экземпляр класса, имея его имя. Есть ли способ сделать это на Java? У меня будет имя пакета и имя класса, и мне нужно иметь возможность создать объект с этим конкретным именем.

ict1991
источник
Мы инстанцируем в класс , и результат является объектом (или: экземпляр ).
Андреас Долк
1
Ответ - да, но я думаю, вы должны спросить , хорошая ли это идея. С большой силой (размышлением) приходит большая ответственность, и вы должны использовать ее, только если вы понимаете и обдумываете последствия.
c1moore 02

Ответы:

241

Два пути:

Метод 1 - только для классов, имеющих конструктор без аргументов

Если в вашем классе есть конструктор без аргументов, вы можете получить Classобъект, используя Class.forName()и использовать этот newInstance()метод для создания экземпляра (хотя имейте в виду, что этот метод часто считается злом, поскольку он может победить проверенные исключения Java).

Например:

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

Способ 2

Альтернативный более безопасный подход, который также работает, если класс не имеет конструкторов без аргументов, - запросить объект вашего класса, чтобы получить его Constructorобъект, и вызвать newInstance()метод этого объекта:

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

Оба метода известны как отражение . Как правило, вам придется перехватить различные исключения, которые могут произойти, в том числе такие, как:

  • JVM не может найти или не может загрузить ваш класс
  • класс, который вы пытаетесь создать, не имеет нужных конструкторов
  • сам конструктор выдал исключение
  • конструктор, который вы пытаетесь вызвать, не является общедоступным
  • был установлен менеджер безопасности, который предотвращает появление отражения
Саймон Никерсон
источник
привет, как только мы создали объект newInstance(), можем ли мы вернуть его нашему собственному объекту?
GMsoF
@Simon, можешь ли ты уточнить / дать указатель на менеджера безопасности?
Ram
Я этого не понимаю. Я хочу получить доступ к классу в неизвестном файле в каком-то другом каталоге, у меня есть только имя пути / файла в виде строки. Строка "dir / unkonwn.java". Вызов Class.forName ("dir / unknown") дает мне ошибки.
John Ktejik
Как мы можем бросить instanceв com.foo.MyClass? учитывая, что com.foo.MyClass - это просто строка
Sanket9394 06
14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
ссадина
источник
15
Стоит отметить, что это не работает, если у класса нет конструктора без параметров (и есть другие конструкторы) или если конструктор без параметров недоступен.
Давуд ибн Карим,
3

используйте Class.forName («Строковое имя класса»). newInstance ();

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

Это вызовет инициализацию класса с именем A.

Чандра Сехар
источник
Не работает для меня, даже с добавленным именем пакета. :(
trusktr 03
3

Чтобы упростить получение полного имени класса для создания экземпляра с помощью Class.forName(...), можно использовать Class.getName()метод. Что-то вроде:

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

Затем вы можете привести объект, который вы получили, к любому классу, которому вы передали makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);
Роберто
источник
1
Разве нельзя просто clazz.newInstance()вместо « getNameтогда» fromName?
user276648
1

Использовать отражение Java

Создание новых объектов. Нет эквивалента вызову метода для конструкторов, потому что вызов конструктора эквивалентен созданию нового объекта (чтобы быть наиболее точным, создание нового объекта включает как выделение памяти, так и создание объекта). Таким образом, ближайший эквивалент предыдущему примеру:

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

который находит конструктор, который обрабатывает указанные типы параметров, и вызывает его для создания нового экземпляра объекта. Ценность этого подхода в том, что он чисто динамический, с поиском и вызовом конструктора во время выполнения, а не во время компиляции.

Корнеро
источник
0
String str = (String)Class.forName("java.lang.String").newInstance();
Чен Харел
источник
0

что-то вроде этого должно работать ...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();
Шашанк Кадне
источник
0

Прямое использование newInstance()устарело, начиная с Java 8. Вам необходимо использовать Class.getDeclaredConstructor(...).newInstance(...)с соответствующими исключениями.

Мел
источник