将类名作为参数传递

我有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); 

很多选择:

  1. 看看标准工厂方法: http : //en.wikipedia.org/wiki/Factory_method_pattern
  2. 使用枚举而不是类枚举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 type = raw.asSubclass(Alert.class); Constructor 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());