Java 将类名作为参数传递
我有三个类,分别是Java 将类名作为参数传递,java,Java,我有三个类,分别是RedAlert、YellowAlert和BlueAlert 在我的类AlertController中,我希望有这样一个方法: public void SetAlert(//TAKE IN NAME OF CLASS HERE//) { CLASSNAME anInstance = new CLASSNAME(); } public void SetAlert(Class class) setAlert(RedAlert.class); public void S
RedAlert
、YellowAlert
和BlueAlert
在我的类AlertController
中,我希望有这样一个方法:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
CLASSNAME anInstance = new CLASSNAME();
}
public void SetAlert(Class class)
setAlert(RedAlert.class);
public void SetAlert(Class clazz)
{
Constructor<?> ctor = clazz.getConstructor();
Object object = ctor.newInstance();
}
AlertController aController = new AlertController();
controller.setAlert("com.y.foo.RedAlert");
例如,我想:
AlertController aController = new AlertController();
SetAlert(RedAlert);
如何将类名作为参数,并基于该类名从类名创建适当的对象?您可以在方法签名中引用类,如下所示:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
CLASSNAME anInstance = new CLASSNAME();
}
public void SetAlert(Class class)
setAlert(RedAlert.class);
public void SetAlert(Class clazz)
{
Constructor<?> ctor = clazz.getConstructor();
Object object = ctor.newInstance();
}
AlertController aController = new AlertController();
controller.setAlert("com.y.foo.RedAlert");
然后在方法中,可以使用newInstance方法创建输入类的实例:
Object obj = class.newInstance();
避免内部依赖关系和初始化:
AlertController aController = new AlertController(new RedAlert());
这个怎么样-
public void SetAlert(Class<?> class){
Object obj = class.newInstance();
if(obj isInstanceOf RedAlert){
RedAlert ra= (RedAlert)obj;
}
...
}
public void SetAlert(类){
Object obj=class.newInstance();
如果(obj isInstanceOf REDARTER){
红色警报ra=(红色警报)obj;
}
...
}
而您可以使用反射等创建它。。。我建议调查一些创造性的设计模式
特别是工厂模式
下面是一个(非常)粗糙的例子:
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;
}
}
无论如何,虽然这是一个非常丑陋的例子,但我想强调的是,也许你可以看看创造性模式,用不同的方式解决你的问题,而不需要传递类名。你可以传递类本身,并使用反射来创建类的新实例,而不是传递类名。下面是一个基本示例(假设所有
XxxAlert
类都是从Alert
类扩展而来):
请注意,最好在T
参数中使用一个超类,否则您(或其他程序员)可以这样做:
setAlert(Object.class);
这显然是错误的。使用反射是可能的。这里是一个给定的类名(作为字符串传递)。该类将在内存中搜索(应该已经加载) 作为字符串传递时要实例化的类的名称应该是完全限定的
void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
Class classTemp = Class.forName(className);
Object obj =classTemp.newInstance();
}
}
使用枚举:
public enum AlertType {RED_ALERT, YELLOW_ALERT, BLUE_ALERT};
// ...
public void SetAlert(AlertType type)
{
// ...
}
// ...
AlertController aController = new AlertController();
SetAlert(AlertType.RED_ALERT);
有很多选择:
使用Java反射从类对象创建对象。如下所示声明您的方法:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
CLASSNAME anInstance = new CLASSNAME();
}
public void SetAlert(Class class)
setAlert(RedAlert.class);
public void SetAlert(Class clazz)
{
Constructor<?> ctor = clazz.getConstructor();
Object object = ctor.newInstance();
}
AlertController aController = new AlertController();
controller.setAlert("com.y.foo.RedAlert");
这是使用类名创建实例的方法。
警报的具体类型必须具有不带参数的公共构造函数
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);
}
}
如果您创建了一个将某组参数传递给构造函数的约定,您也可以这样做,但是您需要在getConstructor()
调用中做一些额外的工作才能找到它。您也可以使用非公共的构造函数,但是,同样,这需要一些额外的工作
传递类文本的建议,RedAlert.class
,没有多大意义。如果调用方在编译时可以使用RedAlert
类,则只需使用其构造函数new RedAlert()
另一种不使用反射的方法是使用一个接口say Alert,并让您的类RedAlert、YellowAlert和BlueAlert实现警报接口
现在,您在AlertController中的方法如下所示:
public void setAlert(Alert alert) {
// Your code goes here
}
现在您可以执行以下操作:
setAlert(new RedAlert());
setAlert(new YellowAlert());
setAlert(new BlueAlert());
为什么不使用工厂模式方法呢
公共接口警报{}
公共类RedAlert实现警报{}
公共类YellowAlert实现警报{}
公共类BlueAlert实现警报{}
公共接口警报工厂{
警报创建();
}
公共类RedAlertFactory实现AlertFactory{
公共警报创建(){
返回新的RedAlert();
}
}
公共类YellowAlertFactory实现AlertFactory{
公共警报创建(){
返回新的YellowAlert();
}
}
公共类BlueAlertFactory实现AlertFactory{
公共警报创建(){
返回新的BlueAlert();
}
}
//您的setAlert方法可能如下所示
公共无效设置警报(警报工厂){
aInstance=工厂->创建();
}
然后你可以做这样的事情。
可以使用您的方法。您需要查看Java反射API!但你为什么想要它?SetAlert(new RedAlert())
有什么问题?@edwardsmatt这是我答案的一部分,否则OP可能会犯错误,在大多数情况下使用Object.class(或任何其他类)调用上一个示例中所示的方法,这比公认的答案要好。通过使用equals
而不是=
并按照您在开始时建议的使用反射,可以大大改进此工厂。否则,想象一下当新的Alert
子类出现时会发生什么。我完全同意!很难确切知道用例是什么,在本例中,您应该只传入实例化的对象。@raniejade的答案是比这个更干净的工厂设计。这里的答案使用了if测试的非OO方法。raniejade使用工厂的子类化。注意:每个工厂只需要一个副本。如果AlertFactory是一个类而不是一个接口,那么它可以包含静态变量,每个工厂一个<代码>公共抽象类AlertFactory{…public readonly static RedAlertFactory red=new RedAlertFactory();…}
则无需在每次使用时创建新工厂:setAlert(AlertFactory.red)
。