【问题标题】:Is there a way with Java Generics to take Generic parameter that requires implementation of 2 interfaces?Java 泛型有没有办法采用需要实现 2 个接口的泛型参数?
【发布时间】:2009-07-17 01:16:01
【问题描述】:

假设我有这个代码 -

public interface ParentInterface1 {
    public List<? extends ChildInterface1> getChildren();
    public void setChildren(List<? extends ChildInterface1> children);
}
public interface ParentInterface2 {
    public List<? extends ChildInterface2> getChildren();
    public void setChildren(List<? extends ChildInterface2> children);
}
public interface ChildInterface1 {
    public String getField();
    public void setField(String field);
}
public interface ChildInterface2 {
    public String getField();
    public void setField(String field);
}
public class LParentImpl implements ParentInterface1, ParentInterface2 {
    private List<ChildImpl> list;
    public List<ChildImpl> getChildren() {
        return list;
    }
    public void setChildren(List<... wants to accept ChildImpl, which 
                                   implements ChildInterface1 & ChildInterface2> children) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
public class ChildImpl implements ChildInterface1, ChildInterface2 {
    private String field;
    public String getField() {
        return field;
    }
    public void setField(String field) {
        this.field = field;
    }
}

有没有办法让 ParentImpl 类中的 setChildren() 工作,而无需从接口和实现中完全删除 Generic 类型?

我想做一些类似的事情 -

public void setChildren(List<? extends ChildInterface1 & ChildInterface2> children) 

这种接口/实现结构对非泛型类型有效,但似乎泛型的运行时擦除的某些方面可能使这不可能?还是我错过了一些神奇的语法?

编辑:使用列表 extends ChildInterface1 & ChildInterface2> 产生这个编译错误 -

...\ParentImpl.java:20: > expected
    public void setChildren(List<? extends ChildInterface1 & ChildInterface2> children) {

【问题讨论】:

    标签: java generics interface


    【解决方案1】:

    您可以指定一个方法,该方法采用实现这两个接口的对象,如下所示:

    public <T extends IFirst & ISecond> void doSomething(T obj) {}
    

    但是,在您的示例中这并不重要,因为您的两个子接口都指定了相同的方法。

    【讨论】:

    • 谢谢乔恩!当我试图完全按照你的回答给我的时候,我偶然发现了这个线程(尽管它没有回答最初的提问者)。我尝试这样做: public static interface Displayable extends Identifiable, Nameable { } public void print(Displayable obj) { System.out.println("[" + obj.getIdentity() + "] " + obj.getName()) ;这不起作用,因为我传递的对象没有实现 Displayable,但不是 Nameable 和 Identifiable 单独。
    • 你刚刚阻止我点击“发布你的问题”。谢谢!。
    【解决方案2】:

    你的问题没有意义。

    ParentInterface1.setChildren 接受List&lt;ChildInterface1&gt;。因此,LParentImpl.setChildern 如此之多,但您正试图限制它,使其不会。

    你可能想说,参数化ParentInterface1/2,但我建议尽可能避免接口的多重继承(不仅仅是涉及泛型的地方)。

    【讨论】:

    • 你是对的。我试图解决你不能满足两个接口的事实 - public void setChildren(List) public void setChildren(List) 因为擦除 - 但我想我在这里想要做什么鉴于语言的机制,这是不可能的。
    • 由于语言规范的原因,您不能同时重载这两种方法(重载是一个静态问题,因此尽管擦除仍然可能)。该方法的最严格的参数类型是 List&lt;? extends ChildInterface1 | ChildInterface2&gt;(无效的 Java),它没有用。不确定您是否可以将其声明为 List&lt;?&gt;
    【解决方案3】:

    你可以这样做:

    public class MyClass<T extends ChildInterface1 & ChildInterface2> { ... }
    

    看看Java Generics Wildcarding With Multiple Classes

    【讨论】:

    • 几乎有效。看我的回答。
    【解决方案4】:

    这不是答案,但我必须感谢 Jorn 的回答!

    在尝试完全按照您的回答给我的结果时,我偶然发现了这个帖子(尽管它没有回答最初的提问者)。我试着这样做:

    public static interface Displayable
        extends Identifiable, Nameable { }
    
    public void print(Displayable obj) {
        System.out.println("[" + obj.getIdentity() + "] " + obj.getName());
    }
    

    这不起作用,因为我传递的对象没有实现 Displayable,但不是 Nameable 和 Identifiable 单独。

    使用 Jorn 的技术,我这样做:

    public <T extends Identifiable & Nameable> void print(T obj) {
        System.out.println("[" + obj.getIdentity() + "] " + obj.getName());
    }
    

    它完美无瑕!

    我希望这对与我有类似问题的其他人有所帮助(并且偶然发现了这个帖子)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      相关资源
      最近更新 更多