Передача имени класса в качестве параметра
У меня есть 3 класса, называемые RedAlert
, YellowAlert
и BlueAlert
.
В моем классе AlertController
я хочу иметь такой метод:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
CLASSNAME anInstance = new CLASSNAME();
}
Так, например, я хочу:
AlertController aController = new AlertController();
SetAlert(RedAlert);
Как взять имя класса в качестве параметра и на основе этого имени класса создать соответствующий объект из имени класса?
Ответы
Ответ 1
Использование отражения возможно. Здесь для данного классаName (проходит как строка). Этот класс будет искать в памяти (он должен быть уже загружен). Имя класса, создаваемого при передаче в виде строки, должно быть полностью квалифицированным
void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
Class classTemp = Class.forName(className);
Object obj =classTemp.newInstance();
}
}
Ответ 2
Вместо передачи имени класса вы можете передать сам класс и использовать отражение для создания нового экземпляра класса. Вот базовый пример (предполагая, что все ваши классы XxxAlert
простираются от класса Alert
):
public <T extends Alert> void setAlert(Class<T> clazzAlert) {
Alert alert = clazzAlert.newInstance();
//use the alert object as you want/need...
}
Теперь вы просто вызываете метод следующим образом:
setAlert(RedAlert.class);
Обратите внимание, что лучше было бы использовать суперкласс в параметре T
, иначе вы (или другой программист) могли бы сделать это:
setAlert(Object.class);
что было бы неправильно.
Ответ 3
Пока вы можете создать его с помощью Reflection и т.д. Я бы предложил исследовать некоторые шаблоны проектирования Creation.
В частности, шаблон Factory
Вот (очень) грубый пример:
public interface Alert {
}
public class BlueAlert implements Alert {
}
public class RedAlert implements Alert {
}
public class YellowAlert implements Alert {
}
public final class AlertFactory {
public <T extends Alert> Alert create(Class<T> clazz) {
Alert toReturn = null;
if (RedAlert.class.equals(clazz)) {
toReturn = new RedAlert();
} else if (YellowAlert.class.equals(clazz)) {
toReturn = new YellowAlert();
} else if (BlueAlert.class.equals(clazz)) {
toReturn = new BlueAlert();
}
return toReturn;
}
}
И затем из вашего метода вы можете использовать:
public void SetAlert(Class alertClass) {
Alert theAlert = new AlertFactory().create(alertClass);
}
В любом случае, хотя это действительно уродливый пример, я пытаюсь подчеркнуть, что, возможно, вы могли бы посмотреть на Creational Patterns и решить свою проблему по-другому, не передавая классные имена.
Ответ 4
Почему бы не использовать шаблонный шаблон factory.
public interface Alert {}
public class RedAlert implements Alert {}
public class YellowAlert implements Alert {}
public class BlueAlert implements Alert {}
public interface AlertFactory {
Alert create();
}
public class RedAlertFactory implements AlertFactory {
public Alert create() {
return new RedAlert();
}
}
public class YellowAlertFactory implements AlertFactory {
public Alert create() {
return new YellowAlert();
}
}
public class BlueAlertFactory implements AlertFactory {
public Alert create() {
return new BlueAlert();
}
}
// your setAlert method could probably look like this
public void setAlert(AlertFactory factory) {
aInstance = factory->create();
}
Тогда вы могли бы сделать что-то вроде этого.
setAlert(new RedAlertFactory()); // or YellowAlertFactory, BlueAlertFactory
Можно использовать ваш подход, используя java.lang.Class # newInstance.
Ответ 5
У вас может быть ссылка класса в вашей сигнатуре метода, что-то вроде этого:
public void SetAlert(Class class)
Затем в вашем методе вы можете создать экземпляр класса ввода с помощью метода newInstance:
Object obj = class.newInstance();
Ответ 6
Как насчет этого -
public void SetAlert(Class<?> class){
Object obj = class.newInstance();
if(obj isInstanceOf RedAlert){
RedAlert ra= (RedAlert)obj;
}
...
}
Ответ 7
Избегайте внутренних зависимостей и инициализаций:
AlertController aController = new AlertController(new RedAlert());
Ответ 8
Использовать перечисления:
public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT};
// ...
public void SetAlert(AlertType type)
{
// ...
}
// ...
AlertController aController = new AlertController();
SetAlert(AlertType.RED_ALERT);
Ответ 9
Много вариантов:
Ответ 10
Используйте Java Reflection для создания объекта из объекта класса. Объявите свой метод следующим образом:
public void SetAlert(Class clazz)
{
Constructor<?> ctor = clazz.getConstructor();
Object object = ctor.newInstance();
}
И затем,
AlertController aController = new AlertController();
SetAlert(RedAlert.class);
Ответ 11
Это способ создания экземпляра с использованием имени класса. Конкретный тип Alert
должен иметь открытый конструктор, который не принимает аргументов.
private Alert alert;
public void setAlert(String className)
{
try {
Class<?> raw = Class.forName(className);
Class<? extends Alert> type = raw.asSubclass(Alert.class);
Constructor<? extends Alert> ctor = type.getConstructor();
this.alert = ctor.newInstance();
} catch (Exception ex) {
throw new IllegalArgumentException("Invalid Alert implementation.", ex);
}
}
Звонящий будет использовать его следующим образом:
AlertController aController = new AlertController();
controller.setAlert("com.y.foo.RedAlert");
Если вы создаете соглашение о передаче определенного набора параметров конструктору, вы также можете это сделать, но вам нужно сделать небольшую дополнительную работу в вызове getConstructor()
, чтобы найти его. Вы также можете использовать конструкторы, которые не являются общедоступными, но, опять же, это требует немного дополнительной работы.
Предложения о передаче литерала класса RedAlert.class
не имеют большого смысла. Если класс RedAlert
доступен для вызывающего во время компиляции, вы просто используете его конструктор new RedAlert()
.
Ответ 12
Другой способ, которым вы можете это сделать, не используя рефлексию, - это использовать интерфейс "Оповещение" и иметь свои классы - RedAlert, YellowAlert и BlueAlert реализовать интерфейс Alert.
Итак, теперь ваш метод в AlertController выглядит так:
public void setAlert(Alert alert) {
// Your code goes here
}
Теперь вы можете сделать:
setAlert(new RedAlert());
setAlert(new YellowAlert());
setAlert(new BlueAlert());