具有另一个泛型类作为参数的泛型类

时间:2015-09-21 19:51:17

标签: java generics nested-generics

我发现自己处于泛型的奇怪情况,到目前为止似乎不可能。我尝试在简单的类中隔离这种情况。我试图完成的是:一个服务类,它调度句柄来处理数据包。每个处理程序都有一个Packet类型参数,因为它应该是每个数据包的处理程序。服务类还有一个Handler类型参数,因为有几种类型的处理程序,因此不同的处理程序类型需要几个服务。这个描述可能不是很清楚,所以这是我做的例子:

.footer_btn {
//Your css
}

.footer_btn:hover {
  background-image: url('image.jpg');
}

有没有办法完成这样的事情或任何建议?感谢

编辑:这是来自manouti答案的修改后的代码(注意:为了清楚起见,我将SomePacket更改为PacketOne)。我遇到的问题是创建ServiceImpl的内容。

public abstract class Service<T extends Handler<?>> {

    //Some random logic

    //If only I could use T<E>
    protected abstract <E extends Packet> void handle(T handler, E packet);

}

public class ServiceImpl extends Service<HandlerOne<?>> {

    @Override
    protected <E extends Packet> void handle(HandlerOne<?> handler, E packet) {
        handler.handle("someString", packet); //ERROR
    }

}

public interface Handler<E extends Packet> {

}

public interface HandlerOne<E extends Packet> extends Handler<E> {

    void handle(Object someObject, E packet);

}

public class HandlerOneImpl implements HandlerOne<SomePacket> {

    @Override
    public void handle(Object someObject, SomePacket packet) {
    }

}

public interface Packet {

}

public class SomePacket implements Packet {

}

2 个答案:

答案 0 :(得分:3)

方法handle需要ObjectE类型的参数(类型参数)。您只指定了第二个。

然后,即使由于Object通配符的捕获转换而在第一个参数中引入?,您仍会收到错误。所以我会选择两个类型参数:

public abstract class Service<E extends Packet, T extends Handler<E>> {
    // Some random logic

    protected abstract void handle(T handler, E packet);

}

public class ServiceImpl<E extends Packet, T extends HandlerOne<E>> extends Service<E, T> {
    @Override
    protected void handle(T handler, E packet) {
        handler.handle(new Object(), packet); // some object as first parameter
    }
}

当前代码的问题在于以下声明:

protected <E extends Packet> void handle(HandlerOne<?> handler, E packet) {
    handler.handle("someString", packet); //ERROR
}

你告诉处理程序,它被输入“某种”数据包类型,以处理类型为E的数据包。在运行时,处理程序的实际数据包类型可能不是E

答案 1 :(得分:0)

你正在面对Java Type系统的限制,为了正确地做到这一点,你需要像Higher Kinded Types这样的东西。 Java并不支持这一点,并且与我已经看到的实现最接近的是(实验)项目HighJ中的类型。 HighJ使用Witness类型来分隔容器和值类型。例如,来自wiki

  

我发现在Java中模拟高阶类型多态的唯一方法是使用我们已经拥有的抽象,即类型参数的抽象。要做到这一点,我们需要分离&#34;容器类型&#34;从它的值类型,然后使其成为一个类型参数。而不是

   List<String> we have something like 
   Something<List, String>.

然而,在生产(Java)项目中执行此操作可能不是一个好主意,因为它很复杂且学习曲线陡峭。我建议你在某个地方简化你的设计。

更高的Kinded类型(泛型的泛型)允许更高级别的抽象(你可以说

   List<T extends Processor<E>> 

例如),为了使您的设计更简单,您可以牺牲抽象(在某处复制某些代码),或者键入安全性(动态语言与高级类型系统一样简洁)。

您可以通过额外的单元测试来弥补类型安全性的损失。