将类名作为参数传递
我有3个名为RedAlert,YellowAlert和BlueAlert的类。
在我的类AlertController中,我希望有一个这样的方法:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//) { CLASSNAME anInstance = new CLASSNAME(); }
所以例如我想:
AlertController aController = new AlertController(); SetAlert(RedAlert);
如何将类名作为参数,并根据该类名从类名创建适当的对象?
使用reflection是可能的。 这里是给定的className(作为字符串传递)。 将在内存中搜索此类(它应该已经加载)。 作为字符串传递时要实例化的类的名称应该是完全限定的
void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class classTemp = Class.forName(className); Object obj =classTemp.newInstance(); } }
您可以传递类本身并使用reflection来创建类的新实例,而不是传递类名。 这是一个基本示例(假设您的所有XxxAlert
类都从Alert
类扩展):
public void setAlert(Class clazzAlert) { Alert alert = clazzAlert.newInstance(); //use the alert object as you want/need... }
现在你只需调用这样的方法:
setAlert(RedAlert.class);
请注意,在T
参数中使用超类会更好,否则您(或其他程序员)可以这样做:
setAlert(Object.class);
这是完全错误的。
为什么不使用工厂模式方法。
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来使用您的方法。
虽然您可以使用Reflection等创建它…我建议调查一些创建设计模式。
特别是工厂模式
这是一个(非常)粗略的例子:
public interface Alert { } public class BlueAlert implements Alert { } public class RedAlert implements Alert { } public class YellowAlert implements Alert { } public final class AlertFactory { public Alert create(Class 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并以不同的方式解决你的问题而不传递类名。
您可以在方法签名中引用Class,如下所示:
public void SetAlert(Class class)
然后在您的方法中,您可以使用newInstance方法创建输入类的实例:
Object obj = class.newInstance();
那这个呢 –
public void SetAlert(Class> class){ Object obj = class.newInstance(); if(obj isInstanceOf RedAlert){ RedAlert ra= (RedAlert)obj; } ... }
避免内部依赖和初始化:
AlertController aController = new AlertController(new RedAlert());
使用枚举:
public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT}; // ... public void SetAlert(AlertType type) { // ... } // ... AlertController aController = new AlertController(); SetAlert(AlertType.RED_ALERT);
很多选择:
- 看看标准工厂方法: http : //en.wikipedia.org/wiki/Factory_method_pattern
- 使用枚举而不是类枚举Alert {Red,Yellow,Green;}
使用Java Reflection从Class对象创建对象。 像这样声明你的方法:
public void SetAlert(Class clazz) { Constructor> ctor = clazz.getConstructor(); Object object = ctor.newInstance(); }
然后,
AlertController aController = new AlertController(); SetAlert(RedAlert.class);
这是使用类名创建实例的方法。 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()
。
另一种不使用reflection就可以做到这一点的方法是让一个接口说出Alert并让你的类–RedAlert,YellowAlert和BlueAlert实现Alert接口。
所以现在你在AlertController中的方法看起来像:
public void setAlert(Alert alert) { // Your code goes here }
现在你可以这样做:
setAlert(new RedAlert()); setAlert(new YellowAlert()); setAlert(new BlueAlert());