[英]Passing class name as parameter
我有3個名為RedAlert
, YellowAlert
和BlueAlert
。
在我的類AlertController
我希望有一個像這樣的方法:
public void SetAlert(//TAKE IN NAME OF CLASS HERE//)
{
CLASSNAME anInstance = new CLASSNAME();
}
所以例如我想:
AlertController aController = new AlertController();
SetAlert(RedAlert);
如何將類名作為參數,並根據該類名從類名創建適當的對象?
使用反射是可能的。 這里是給定的className(作為字符串傳遞)。 將在內存中搜索此類(它應該已經加載)。
作為字符串傳遞時要實例化的類的名稱應該是完全限定的
void createInstanceOfClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
Class classTemp = Class.forName(className);
Object obj =classTemp.newInstance();
}
}
您可以傳遞類本身並使用反射來創建類的新實例,而不是傳遞類名。 這是一個基本示例(假設您的所有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);
這是完全錯誤的。
雖然您可以使用Reflection等創建它...我建議調查一些創建設計模式。
特別是工廠模式
這是一個(非常)粗略的例子:
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並以不同的方式解決你的問題而不傳遞類名。
為什么不使用工廠模式方法。
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來使用您的方法。
您可以在方法簽名中引用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);
很多選擇:
使用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()
。
另一種不使用反射就可以做到這一點的方法是讓一個接口說出Alert並讓你的類--RedAlert,YellowAlert和BlueAlert實現Alert接口。
所以現在你在AlertController中的方法看起來像:
public void setAlert(Alert alert) {
// Your code goes here
}
現在你可以這樣做:
setAlert(new RedAlert());
setAlert(new YellowAlert());
setAlert(new BlueAlert());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.