Как выбрать определенный класс для создания экземпляров во время выполнения в Java?
Я получаю около 20 классов с именами A, B, C,...X, Y, Z.
И пользователь отправит мне какое-то сообщение, я выберу один из классов для создания экземпляра в зависимости от содержимого сообщения. Сообщение совпадает с именем соответствующего класса.
Я могу написать оператор switch case, чтобы сделать это, например:
switch (msg):
case "A" :
class = new A();
break;
case "B" :
class = new B();
break;
case "C" :
class = new C();
break;
...
Есть ли более краткий способ сделать это? Я не могу представить, насколько скучна кодировка, если я получу 1000 классов.
6 ответов
Ты можешь использовать Class.forName()
за это:
Class c = Class.forName("foo.bar.MyClass"); // requires full class name including package
Object object = c.newInstance();
Смотрите документацию Class.forName()
Больше подробностей. Эти особенности называются отражением. Oracle предоставляет хороший раздел документации для такого рода функций.
Другие предложили использовать фабрику, и они правы.
Я предпочитаю использовать enum
для моей фабрики.
interface I {
}
class A implements I {
}
class B implements I {
}
class C implements I {
}
enum Factory{
A {
@Override
A create() {
return new A();
}
},
B {
@Override
B create() {
return new B();
}
},
C {
@Override
C create() {
return new C();
}
};
// Constructors.
abstract I create();
// Construct a named class.
public I create(String type) {
return Factory.valueOf(type).create();
}
}
Попробуйте это: -
Class myclass = Class.forName("Your.Class.MyClass");
Object o= myclass .newInstance();
forName ()
Возвращает объект Class, связанный с классом или интерфейсом с заданным именем строки.
Прежде всего, такая проблема присуща хорошему дизайну. Тип метода, о котором вы говорите, - это метод Factroy.
Вы можете использовать case, но чаще используется блок if-else. Так...
if(msg.equals(A)) {
return new A();
} else if(msg.equals(B)) {
return new B();
} ....
Здесь, предполагая, что A & B являются строками, мне нравится определять их как константы (public static final
).
Хотя оба варианта немного беспорядочные, в большинстве случаев люди используют блок if-else, но это более стандартная процедура.
- Получить
Class
экземпляр изClassLoader
, передавая имя, которое вам нужно. - Вызов
newInstance
в теме.
Как я вижу, у каждого есть свое решение, поэтому я покажу вам мое
тебе нужно:
interface MyInterface {
}
class A implements MyInterface {
}
class B implements MyInterface {
}
interface Factory {
MyInterface createInstance();
}
class FactoryA implements Factory {
@Override
public MyInterface createInstance() {
return new A();
}
}
class FactoryB implements Factory {
@Override
public MyInterface createInstance() {
return new B();
}
}
enum MyEnum {
A(new FactoryA()), B(new FactoryB());
Factory factory;
MyEnum(Factory factory) {
this.factory = factory;
}
MyInterface getInstance() {
return factory.createInstance();
}
}
тогда все, что вам нужно сделать, это создать таблицу поиска, и ваш оператор switch будет заменен на MyEnum.find(msg).getInstance()
с этим решением вам не нужно беспокоиться об обработке любых исключений