首页 > 解决方案 > 泛型对象参数的类型问题

问题描述

我有一个抽象类,

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

它编译,但警告我演员未选中。

  1. 在第一种情况下,为什么编译器不知道我的Manager类正在扩展WebserviceIntegration,这使得它与F类兼容?

  2. 在第二种情况下,我怎样才能进行安全的演员表?我无法检查manager instanceof F,那我该怎么办?

谢谢

标签: javagenerics

解决方案


这不是很清楚,但根据您的问题,我认为失败的代码位于泛型类的构造函数中。

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();
    }

}

推荐阅读