我有一个抽象类,
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{
//...
}
}
Ofc 如果我创建一个新窗口NewUserWindow<?, Manager> window = new NewUserWindow<>(new OtherClass(), new Manager());
并保存传递给窗口的 bean,一切都很好。
现在我想做的是在构造函数中保存一个新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
核对,那我该怎么办?
谢谢
不是很清楚,但根据您的问题,我认为失败的代码位于泛型类的构造函数中。
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(它不是编译,因为你只知道F类型是扩展的WebserviceIntegration,但它可以是任何扩展WebserviceIntegration的类型
因此,如果您还有其他扩展Webservice集成的类,例如
public class NoManager extends WebserviceIntegration {
//...
}
你创造了另一个NewUserWindow<?, NoManager> noManagerWindow = new NewUserWindow<>(new OtherClass(), new NoManager())
你不能做类似noManagerWindow.saveConnectedBean(new Manager())
2(你不应该做一个转换,因为你不能确定F是经理的类型。
我认为您要做的只是使用WebserviceIntegration类型,而不使用任何泛型。
也许是这样的事情。将抽象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
中的方法实现,因为实际的子类型未知。