【问题标题】:Returning List of Generic Type Objects using Wildcards使用通配符返回泛型类型对象列表
【发布时间】:2014-03-13 11:59:46
【问题描述】:

要求:

  • 需要我的方法返回两个指定对象之一的列表。
  • 需要将上述方法的结果存储为两个指定对象之一的列表。

声明了一个基于通配符返回通用列表的方法。 声明部分正确,但方法调用失败。

class Z{/*TemplateClass*/}
public class A extends Z{}
public class B extends Z{}

测试类:

public List<? extends Z> getGenericList(boolean test){
    if(test){
        List<A> aList = new ArrayList<A>();
        aList.add(new A());
        return aList;
    }
    else{
        List<B> bList = new ArrayList<B>();
        bList.add(new B());
        return bList;
    }
}

这是我的要求。我需要类似下面的代码。

List<A> testAList = getGenericList(true);
List<B> testBList = getGenericList(false);

给我一​​个编译器错误。

类型不匹配:无法从 List 扩展到 List 类型不匹配:无法从 List到列表

我理解这背后的逻辑。如果我们传递一个 false 并将返回的 B 列表存储为 A 列表,这是错误的。 但是当我使用下面的代码时:

List<? extends Z> testList = getGenericList(true);

它编译得很好。但这超出了我的目的。我无法访问 A 或 B 中的方法,因为 testList.get(index) 返回 Z 类型的对象,我希望在其中获得 A 或 B。

如果我的代码绝对错误,那么任何正确方向的指针都将不胜感激。

【问题讨论】:

  • 你知道Type Erasure吗?为什么不返回List&lt;Z&gt;
  • 明白了。原始对象被保留。稍后使用 Z 和类型转换是解决方案之一。我想知道是否可以在没有铸造部分的情况下完成。
  • Z 只是我使用的一个模板。它绝对是空的。我需要的所有逻辑/数据都将出现在AB 中。如果对象是Z,我将如何访问这些数据而不将其类型转换为AB
  • 在 Z 中定义合约
  • 您的 cmets 帮助我解决了我的问题。谢谢艾略特。

标签: java generics collections


【解决方案1】:

您可以强制转换结果,这会使编译器错误消失,但您会遇到不安全的强制转换,这看起来像是代码异味:

List<A> testAList = (List<A>) getGenericList(true);
List<B> testBList = (List<B>)getGenericList(false);

此外,如果布尔输入不是严格要求,您也可以执行以下操作:

public <T extends Z> List<T> getGenericList(Class<T> klass) {
        List<T> list = new ArrayList<T>();
        try {
            list.add(klass.newInstance());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return list;
    }

【讨论】:

  • 是的。腐烂。我工作的人是德国牧羊犬。没有类型转换有没有办法做到这一点?
  • 选择这个作为答案,因为它直接回答了我的问题。即使我使用@Elliott 的方法来解决我的问题。
【解决方案2】:

不会发生。您要求的类型根本无法在 java 类型系统中表达,例如 List&lt;A&gt; + List&lt;B&gt;

最接近的就是一种延续传球风格;您创建另一个抽象类,如HomogeneousListAB,带有访问者界面和接受方法。然后你可以从 getGenericList 返回其中之一。

abstract class HomogeneousListAB {
    interface Visitor {
        void ifListA( List< A > la );
        void ifListB( List< B > la );
    }
    abstract public accept( Visitor v );
}

// inside getGenericList true branch
final List< A > laOut = // whatever
return new HomogeneousListAB() {
    public accept( Visitor v ) {
        v.ifListA( laOut );
    }
};

【讨论】:

  • +1 表示您的方法,虽然乍一看有点复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 2017-01-21
相关资源
最近更新 更多