【问题标题】:Instantiating Generic Type in class: V extends List在类中实例化通用类型:V 扩展列表
【发布时间】:2017-01-01 18:26:22
【问题描述】:

我正在尝试开发一个与扩展 java.util.List 的对象一起使用的类,例如 ArrayList。以下是我认为应该编译的示例(假设有必要的 import 语句):

public class MyClass<V extends List> {

    V myList = new ArrayList();

    MyClass<ArrayList> myinstance = new MyClass<>();
}

虽然“myinstace”没有问题,但编译器在尝试实例化“myList”时会失败:

MyClass.java:[17,16] 不兼容类型:java.util.ArrayList 不能 转换为 V

据我了解泛型,声明:

<V extends List>

暗示无论“V”是什么类型,它都必须是“List”的子类。那么,为什么我不能像上面那样实例化,有什么正确的方法可以在类中实例化一个“V”类型的对象吗?

此外,如何在类的方法中返回“V”类型的对象?

public V getSomeData(){
    // How do we create our object of type "V"?
}

背景

我有一个界面,PatternElement:

public interface PatternElement<D,W> {

    /**
     * The data that this element contains or signifies.
     * @return 
     */
    public D getData();

    /**
     * The width of this pattern element within a pattern.
     * @return 
     */
    public W getWidth();

}

我正在尝试开发一个子类 PolyPatternElement,它本身可以包含许多“数据”和“宽度”项。我认为下面的代码会完成这个......

public class PolyPatternElement<V extends List, W extends List> implements PatternElement<V,W>{


    @Override
    public V getData() {
        ArrayList data = new ArrayList();
        return data;
    }

    @Override
    public W getWidth() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

} 

很遗憾,“getData”无法编译。因此,我缩小了问题范围并提出了原始问题。经过反馈,我认为更好的 PolyPatternElement 定义是:

public class PolyPatternElement<V,W> implements PatternElement<List,List>{


    @Override
    public List getData() {
        ArrayList data = new ArrayList();
        return data;
    }

    @Override
    public List getWidth() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}

这允许声明一个 PolyPatternElement 对象,其类型是我打算的任何 List 实现。

【问题讨论】:

  • 如果在每种情况下都是ArrayList,你为什么要使用通用的V
  • 如果有人会选择V LinkedList 喜欢MyClass&lt;LinkedList&gt; 怎么办?那么V myList = new ArrayList(); 有意义吗? V 不代表(不能持有)任何列表,而是一些特定的但尚未未知的列表。
  • 啊,这很有趣@Pshemo。如果我想返回这种类型的对象“V”怎么办?在我的课堂上......我添加了。
  • @Vance-Turner 正确的方法是构造函数 MyClass(V myList) 并在其中设置 myList
  • 我不确定您遇到了什么问题。如果您的myListV 类型并且它包含一些实例(假设您通过构造函数MyClass(V myList) 或方法setList(V myList) 传递它)那么您可以创建方法,该方法也将返回此列表,如V getList(){ return myList;}。所以返回没有问题。你不能做的是使用new 运算符创建V 实例,或者因为我们不知道V 将代表什么(更不用说泛型在运行时被删除)。

标签: java generics arraylist extends


【解决方案1】:

尝试(未经测试):

public class PolyPatternElement<V, W> implements PatternElement<List<V>, List<W>>

【讨论】:

  • 谢谢,这正是我想要的。
【解决方案2】:

...意味着无论“V”是什么类型,它都必须是“List”的子类。

在泛型类中,您不能简单地实例化泛型参数类的对象。

public class MyClass<V extends List> {

    V myList = new ArrayList();  // <-- What if 'V' is 'LinkedList'?

}

您要么必须提供类或带有构造函数的对象:

public class MyClass<V extends List> {

    private final V myList;

    public MyClass(V theList) {
        this.myList = theList;
    }

    public MyClass(Class<V> listType) {
        this.myList = listType.newInstance(); // works only if 'listType' has default constructor.
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 2018-06-16
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    相关资源
    最近更新 更多