<e extends =“”可比较的<e =“”>&gt; </e>的可实例化Java通用

时间:2014-05-24 23:42:56

标签: java generics

我有一个班级(让我们说一个手推车[又名“购物车”在en-US]),它加载了一堆字符串或整数的对象。用户指定一个标志作为输入,以说明应如何读取输入。小车类只关心对象是否可以进行分类。但是,我无法为字符串和整数重用相同的手推车对象。要解释一下,这是一个MWE:

import java.util.TreeSet;

public class Trolley<E extends Comparable<E>> {
    public TreeSet<E> items;

    public Trolley(){
        items = new TreeSet<E>();
    }

    public boolean addItem(E item){
        return items.add(item);
    }

    public static void main(String args){
        // read from input
        boolean numeric = false;

        Trolley<?> items = null;
        if(numeric)
            items = new Trolley<Integer>();
        else items = new Trolley<String>();

                // items will be parsed from a file
        if(numeric){
                        // compiler warning about generic mismatch
            items.addItem(42);
        } else{
                        // compiler warning about generic mismatch
            items.addItem("42");
        }
    }
}

这会在addItem(.)来电时给出编译器警告。

小车只会对物品进行分类并将它们打印成字符串(即输入是数字还是字符串,后续代码无关紧要。)

同样,这只是一个类似MWE的类比我想要做的事情(实际上,我想将有向图加载到内存中,如果输入可选地预先进行了字典编码,则加载整数就是节省内存)。 / p>


我的问题是如何配置泛型以允许使用相同的手推车对象来抽象整数和字符串输入?

我尝试了一些诸如上面的通配符之类的内容,例如Trolley<? extends Comparable<?>> items = new Trolley<? extends Comparable<?>>(),但这也没有用。我想这里的直觉问题是我可以向Trolley添加任何对象,这些对象可能无法相互比较,就像字符串和整数的混合,而我希望Trolley对象只能接受一种Comparable ......但任何类型。)

(编辑:我应该补充一点,我宁愿避免使用像Item这样的包装类,因为这段代码会受到内存限制。)

2 个答案:

答案 0 :(得分:4)

Trolley<?>是特定类型的Trolley,但我们不知道哪种类型。

在您的代码中,它可能是Trolley<Integer>Trolley<String>

因此,编译器不允许向该小车添加除null之外的任何内容,因为其实际类型仅在运行时确定。

要使代码编译而不需要太多更改,您需要为Integer创建一个分支,为String创建一个分支:

public static void main(String args) {
  boolean numeric = false;

  if (numeric) {
    Trolley<Integer> trolley = new Trolley<>();
    trolley.addItem(42);
  } else {
    Trolley<String> trolley = new Trolley<>();
    trolley.addItem("42");
  }
}

答案 1 :(得分:1)

我使用的最终解决方案(灵感来自@assylias的答案):

public static void main(String args) {
  boolean numeric = false;

  Trolley<? extends Comparable<?>> trolley = null;
  if (numeric) {
    Trolley<Integer> trolleyN = new Trolley<Integer>();
    trolleyN.addItem(42);
    trolley = trolleyN;
  } else {
    Trolley<String> trolleyS = new Trolley<String>();
    trolleyS.addItem("42");
    trolley = trolleyS;
  }

  // use trolley in "read-only" mode
}