Java 类继承:泛型扩展泛型
假设我有一节简单的课Java 类继承:泛型扩展泛型,java,generics,inheritance,Java,Generics,Inheritance,假设我有一节简单的课 public class MyObject { } 以及处理MyObject子类的处理程序接口 public interface MyObjectHandler<V extends MyObject>{ List<V> handle(List<V> objects); } 不起作用。在handler.handle(objects)中,我得到handle(java.util.List您不需要处理程序是泛型的,只需要对象: pu
public class MyObject {
}
以及处理MyObject子类的处理程序接口
public interface MyObjectHandler<V extends MyObject>{
List<V> handle(List<V> objects);
}
不起作用。在
handler.handle(objects)
中,我得到handle(java.util.List您不需要处理程序是泛型的,只需要对象:
public abstract class HandlerChain<V extends MyObject> {
private List<MyObjectHandler<V>> handlers;
public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}
public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
公共抽象类HandlerChain{
私有列表处理程序;
公共HandlerChain(列表处理程序){
this.handlers=handlers;
}
公共列表(列表对象){
for(MyObjectHandler:处理程序){
objects=handler.handle(对象);
}
归还物品;
}
}
这允许:
new HandlerChain<BigObject>(Arrays.asList(new BigHandler1(), new BigHandler2())) {
// ...
};
newhandlerchain(Arrays.asList(new BigHandler1(),new BigHandler2()){
// ...
};
编辑:如果你比较和挖掘,唯一的区别是G_H使用List解决方案1
这一个可以工作,但在handler.handle(objects)中,我作为原始类型“MyObjectHandler”的成员得到了对“handle(List)”的未选中调用,因此我应该添加@SuppressWarnings(“未选中”),这不是很好
实际上,因为MyObjectHandler
是泛型类型,但您没有在HandlerChain
的类型参数中为其指定类型
解决方案2
不起作用。在handler.handle(对象)中,我获取的句柄(java.util.List>)无法应用于(java.util.List)。在这种情况下,为什么我不能将对象传递给处理程序?通配符扩展MyObject,而V扩展MyObject。这还不够吗
没有。?extends MyObject
基本上说它是针对某个未指定类型的扩展MyObject
,但你没有说是哪个。你可以创建一个类公共类BigHandlerChain
,但向Docain
提供一个SmallObject
实例列表
解决方案3
这是可行的,但在本例中,我应该将BigHandlerChain定义为类BigHandlerChain扩展了AbstractHandlerChain。但是BigObjectHandler已经包含了关于类的信息,这些信息可以由它来处理,所以它是信息复制
事实上,这里有一些重复的信息,但是当像这样合成泛型类型时,很可能会发生这种情况。因为您的doChain
方法对某个类型进行操作,所以必须指定该类型可以执行的操作。将其视为您希望处理BigObject
列表,并且您提供的处理程序必须能够处理大对象
解决方案4
这是一个解决方案,我希望它来自java,但它不起作用!我不能像这样声明类…类HandlerChain。为什么我可以在MyObjectHandler之后使用通配符,但不能使用此构造
问题是V
表示某种特定类型,而不是通配符,因此需要指定V是什么
换句话说,您的解决方案3是正确的方法,尽管有一些重复的信息。不幸的是,您将在Java中看到更多这方面的内容。getter/setter可以说是不必要的样板,因为字段上的特定修饰符关键字可以实现相同的效果(如在Ruby中)
但是请注意,如果指定公共抽象类HandlerChain
,则指定该链仅适用于一种特定类型的MyObjectHandler
。因为我认为您可能需要一个能够处理相同对象类型的不同处理程序链,最好只指定一个g该对象类型:
public abstract class HandlerChain<V extends MyObject> {
private List<MyObjectHandler<V>> handlers;
public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}
public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
公共抽象类HandlerChain{
私有列表处理程序;
公共HandlerChain(列表处理程序){
this.handlers=handlers;
}
公共列表(列表对象){
for(MyObjectHandler:处理程序){
objects=handler.handle(对象);
}
归还物品;
}
}
解决方案4很简单:Java编译器希望通配符一起声明,然后使用:
public abstract class HandlerChain<V extends MyObject, T extends MyObjectHandler<V>>
{
private List<T> handlers;
public List<V> doChain(List<V> objects)
{
for (T handler : handlers)
{
objects=handler.handle(objects);
}
return objects;
}
}
公共抽象类HandlerChain
{
私有列表处理程序;
公共列表(列表对象)
{
for(T处理程序:处理程序)
{
objects=handler.handle(对象);
}
归还物品;
}
}
这个问题看起来相关/相同:+1对于你所做的研究来说。看起来你问题的关键是你希望
中的V声明V,而事实上Java编译器希望它已经声明。唉,你不是唯一一个希望这样做的人。但事实就是这样。你的研究是正确的rect,你没有错过任何东西。由于其他两个答案比我快了几分钟,这里有一个显示两个答案使用的方法的示例。我编辑了它。在我完成我的答案时,你的更简洁的答案出现了,我意识到通配符实际上是不必要的,并且在给我打电话时会妨碍我当涉及到泛型时,我总是发现我实际上必须在我的IDE中尝试一些东西,然后才能全面了解它。
public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
public abstract class HandlerChain<T extends MyObjectHandler<V extends MyObject>> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
public abstract class HandlerChain<V extends MyObject> {
private List<MyObjectHandler<V>> handlers;
public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}
public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
new HandlerChain<BigObject>(Arrays.asList(new BigHandler1(), new BigHandler2())) {
// ...
};
public abstract class HandlerChain<V extends MyObject> {
private List<MyObjectHandler<V>> handlers;
public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}
public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
public abstract class HandlerChain<V extends MyObject, T extends MyObjectHandler<V>>
{
private List<T> handlers;
public List<V> doChain(List<V> objects)
{
for (T handler : handlers)
{
objects=handler.handle(objects);
}
return objects;
}
}