我有一个抽象类
public abstract class WebserviceIntegration {
//...
}
许多类中都使用了
public class Manager extends WebserviceIntegration {
//...
}
现在,我已经建立了一个类,该类将通用类的抽象类作为F
自变量,并且在其内部具有方法:
public class NewUserWindow<T, F extends WebserviceIntegration> extends Window {
public NewUserWindow(T objOne, F objTwo) {
//...
saveConnectedBean(objTwo); //no problems here
}
public void saveConnectedBean(F bean) throws MyException{
//...
}
}
如果我创建一个新窗口NewUserWindow<?, Manager> window = new NewUserWindow<>(new OtherClass(), new Manager());
并保存传递给该窗口的bean,Ofc一切都很好。
现在我想做的是在构造函数中保存一个新 Manager
:
public NewUserWindow(T objOne, F objTwo) {
//...
Manager manager = new Manager();
//... setting manager stuff
saveConnectedBean(manager); //does not compile
}
编译器现在阻止我说saveConnectedBean(F) in NewUserWindow cannot be applied to (my.package.path.Manager)
。
如果我用
saveConnectedBean((F)manager);
它可以编译,但警告我演员表未选中。
在第一种情况下,为什么编译器不知道我的Manager
类正在扩展WebserviceIntegration
,从而使其与F
类兼容?
在第二种情况下,如何进行安全投射?我无法与manager instanceof F
核对,该怎么办?
谢谢
答案 0 :(得分:3)
这不是很清楚,但是根据您的问题,我认为失败的代码位于通用类的构造函数中。
1)编译器认为您对F
声明的调用是因为在通用类内部,编译器不知道F
的确切类型。不要忘记泛型只是编译工件。
因此,如果在构造函数中实例化Manager
变量,例如:
Manager manager = new Manager();
但是您声明了通用类型,例如NewUserWindow<?, OtherSubClass> window = ...
它将破坏类型安全性。
2)避免在通用类中使用instanceof
。它在某种程度上破坏了通用目的。
作为替代方案,您应该从通用实例的客户端传递Manager
,例如:
Manager manager = new Manager();
NewUserWindow<?, Manager> newUserWindow = new NewUserWindow<>(new ..., manager);
newUserWindow.saveConnectedBean(manager);
根据您的评论:
假设我无法跨解决方案2运行,是否还有其他方法可以解决 安全铸造?
您可以通过创建一个NewUserWindow
抽象类来实现,该抽象类将返回F
的方法声明为抽象。
public abstract class NewUserWindow<T, F extends WebserviceIntegration> extends Window {
public NewUserWindow(T objOne, F objTwo) {
F f = createF();
saveConnectedBean(f);
}
public abstract F createF();
public void saveConnectedBean(F bean) throws MyException{
//...
}
}
并实现它,例如:
public ManagerUserWindow extends NewUserWindow<T, Manager> extends Window {
public Manager createF(){
return new Manager();
}
}
答案 1 :(得分:1)
也许是这样。将抽象save
方法添加到WebserviceIntegration
public static abstract class WebserviceIntegration {
public abstract void save();
}
在WebserviceIntegration
的每个子类中实现此方法
public static class Manager extends WebserviceIntegration {
@Override
public void save() { // saving Manager here }
}
因此saveConnectedBean
现在可以接受WebserviceIntegration
public void saveConnectedBean(WebserviceIntegration bean) { }
这应该是安全的,因为WebserviceIntegration
的每个子类型都必须实现save
功能。
或者,您可以引入新的方法类型参数
public <B extends WebserviceIntegration> void saveConnectedBean(B bean) { }
在这种情况下,saveConnectedBean
仅限于使用WebserviceIntegration
中的方法来实现,因为实际的子类型是未知的。