Javagenerics如何与C ++模板不同? 为什么我不能使用int作为参数?

我正在努力创造

ArrayList<int> myList = new ArrayList<int>(); 

在Java中,但这是行不通的。

有人可以解释为什么int作为types参数不起作用?
使用Integer类为int原始的作品,但有人可以解释为什么int不被接受?

Java版本1.6

Javagenerics与C ++模板非常不同,我不打算在此列出差异。 (有关更多详细信息,请参阅C ++和Java中的“通用”types之间的区别 。)

在这种特殊情况下,问题是不能使用基元作为genericstypes参数(请参阅JLS第4.5.1节 “types参数可能是引用types或通配符”)。

但是,由于自动装箱,你可以做这样的事情:

 List<Integer> ints = new ArrayList<Integer>(); ints.add(3); // 3 is autoboxed into Integer.valueOf(3) 

这样可以消除一些痛苦。 不过,这肯定会影响运行效率。

int不起作用的原因是你不能在Java中使用原始types作为通用参数。

至于你是真正的问题,C ++模板与Javagenerics是如何不同的,答案是…真的非常不同。 实质上两种完全不同的方法来实现类似的最终效果。

Java倾向于关注generics的定义。 通用定义的有效性是通过只考虑generics中的代码来检查的。 如果参数没有被适当的约束,那么就不能对它们执行某些操作。 它最终被调用的实际types不被考虑。

C ++是相反的。 只有最less的validation是在模板本身上完成的。 它只是需要被parsing才能被认为是有效的。 定义的实际正确性是在使用模板的地方完成的。

他们是非常不同的概念,可以用来执行一些但不是全部相同的任务。 正如其他答复中所说的那样,要花所有的分歧都需要相当多的时间,但这是我所看到的广泛的笔触。

generics允许运行时多态容器通过一个通用容器的实例化。 在Java中,所有的(非原始的)对象都是引用,并且所有的引用都是相同的大小(并且有一些相同的接口),所以可以由字节码来处理。 然而,只有字节码的实例化的必要含义是types橡皮擦; 你不能告诉容器被实例化了哪个类。 这在c ++中不起作用,因为有一个根本不同的对象模型,对象并不总是引用。

模板允许通过多个实例化编译时间多态容器(以及通过在c ++types系统上提供(当前弱types)语言的模板元编程)。 这允许给定types的专门化,不利的一面是潜在的“代码膨胀”,不需要一个以上的编译实例化。

模板比generics更强大; 前者实际上是embedded在c ++中的另一种语言,而据我所知,后者仅在容器中有用

这是因为int是一个原始的,这是一个已知的问题 。

如果你真的想,你可以inheritance/写你自己的collections,可以做到这一点。

Java中不能使用基本types作为types参数。 Java的generics值得通过types擦除,这意味着编译器会检查您是否使用了定义它们的types,但在编译时,所有东西都被当作Object。 由于int和其他基元不是对象,所以不能使用。 相反,使用Integer。

你可以尝试GNU Trove中的TIntArraList,它将像int值的ArrayList那样工作。

主要区别在于它们的实现方式,但是它们的名字可以准确地描述它们的实现。

模板的行为与模板类似。 所以,如果你写:

 template<typename T> void f(T s) { std::cout << s << '\n'; } ... int x = 0; f(x); ... 

编译器会应用这个模板,所以在最后编译器将这些代码看作是:

 void f_generated_with_int(int s) { std::cout << s << '\n'; } ... int x = 0; f_generated_with_int(x); ... 

因此,对于每个用于调用f的types,新代码都是“生成的”。

另一方面,generics只是被types化的,然后所有types的信息被删除。 所以,如果你写:

 class X<T> { private T x; public T getX() { return x; } public void setX(T x) { this.x = x; } } ... Foo foo = new Foo(); X<Foo> x = new X<>(); x.setX(foo); foo = x.getX(); ... 

Java编译它就像:

 class X { private Object x; public Object getX() { return x; } public void setX(Object x) { this.x = x; } } ... Foo foo = new Foo(); X x = new X(); x.setX(foo); foo = (Foo)x.getX(); ... 

到底:

  • 模板需要实例化每个调用模板函数(编译每个.cpp文件),所以模板编译速度较慢
  • 与generics不能使用原语,因为它们不是Object ,所以generics不太灵活