Java泛型与C++模板有何不同?为什么我不能使用int作为参数?

yes*_*aaj 51 c++ java generics

我正在努力创造

ArrayList<int> myList = new ArrayList<int>();
Run Code Online (Sandbox Code Playgroud)

在Java但这不起作用.

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

Java版本1.6

Mic*_*ers 66

Java泛型与C++模板有很大的不同,我不打算在这里列出差异.(有关更多详细信息,请参阅C++和Java中"通用"类型之间的区别?)

在这种特殊情况下,问题是您不能将原语用作泛型类型参数(请参阅JLS§4.5.1:"类型参数可以是引用类型或通配符.").

但是,由于自动装箱,您可以执行以下操作:

List<Integer> ints = new ArrayList<Integer>();
ints.add(3); // 3 is autoboxed into Integer.valueOf(3)
Run Code Online (Sandbox Code Playgroud)

这样可以消除一些痛苦.但它肯定会损害运行时效率.


Jar*_*Par 25

int不起作用的原因是您不能将原始类型用作Java中的泛型参数.

至于你的实际问题,C++模板与Java泛型有何不同,答案是......真的不一样.它实质上是实现类似最终效果的两种完全不同的方法.

Java倾向于关注泛型的定义.也就是说,只考虑泛型中的代码来检查泛型定义的有效性.如果参数未被适当约束,则无法对它们执行某些操作.最终调用它的实际类型不予考虑.

C++恰恰相反.只对模板本身进行了最少的验证.它实际上只需要可解析为有效.定义的实际正确性在使用模板的位置完成.

  • @Faisal:为了保持最新,我应该提一下,因为您的评论"概念"已从C++ 0x(现在可能是C++ 0B)中删除.我们说,这不是普遍受欢迎的决定. (4认同)
  • +1试图解释差异的英勇:-)(虽然我可能会对C++模板的最小验证产生问题 - 任何不依赖于模板参数的代码都会被完全检查) (2认同)

Tod*_*ner 9

它们是非常不同的概念,可用于执行某些但不是所有相同的任务.正如在其他回复中所说的那样,需要花费相当多的时间来讨论所有的差异,但这就是我所看到的广泛的笔触.

泛型允许通过通用容器的单个实例化运行时多态容器.在Java中,所有(非原始)对象都是引用,并且所有引用都是相同的大小(并且具有一些相同的接口),因此可以由字节码处理.然而,仅具有字节代码实例化的必要含义是类型擦除器; 你无法分辨容器被实例化的类.这在c ++中不起作用,因为对象模型根本不同,对象并不总是引用.

模板允许通过多个实例化编译时多态容器(以及通过在c ++类型系统上提供(当前弱类型)语言的模板元编程).这允许给定类型的特化,缺点是需要多个编译实例化的潜在"代码膨胀".

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


kra*_*mir 8

主要区别在于它们的实现方式,但它们的名称准确地描述了它们的实现.

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

template<typename T>
void f(T s)
{
    std::cout << s << '\n';
}

...
int x = 0;
f(x);
...
Run Code Online (Sandbox Code Playgroud)

编译器应用模板,因此最终编译器将代码视为:

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

...
int x = 0;
f_generated_with_int(x);
...
Run Code Online (Sandbox Code Playgroud)

因此,对于用于调用f新代码的每种类型都是"生成"的.

另一方面,泛型只是类型检查,但所有类型信息都被删除.所以,如果你写:

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();
...
Run Code Online (Sandbox Code Playgroud)

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();
...
Run Code Online (Sandbox Code Playgroud)

到底:

  • 模板需要实例化每个对模板化函数的调用(在编译每个.cpp文件时),因此编译模板的速度较慢
  • 使用泛型,你不能使用原语,因为它们不是Object,所以泛型不太通用