具有原始类型但没有类型参数的ArrayList()中的get()方法行为

时间:2014-10-12 09:41:26

标签: java generics collections

我正在研究Java集合。 我发现了一些奇怪的事情并没有弄清楚为什么会这样。 所以这就是场景。

ArrayList al = new ArrayList();
al.add("Hello World");
//The below line is creating some confusion
System.out.print(al.get(0));    

现在最后一行是印刷" Hello World"原样。 但由于我没有使用任何类型参数,它应该给出一个返回的对象类型。所以它应该调用对象的toString()而不是字符串的toString()

它是否依赖于返回类型(如Object)保存的对象类型(如此处为String)。 请帮忙。

3 个答案:

答案 0 :(得分:1)

如果您想从集合中返回String,则必须使用String类型参数对其进行初始化:

ArrayList<String> al = new ArrayList<String>();
//       ^^^^^^^^                   ^^^^^^^^
al.add("Hello World");
String value = al.get(0);  //<-- now you can get Strings

现在,您只能获取对象,并且在返回原始类型之前必须进行投射:

ArrayList al = new ArrayList();
al.add("Hello World");
Object object = al.get(0); //<-- ok
String value = (String)al.get(0); // <-- ok
value = al.get(0);  //<-- wont compile

修改

ArrayList al = new ArrayList();
al.add("Hello World");
Object object = al.get(0); //<-- ok
String value = object.toString();

在这种情况下,调用object.toString()只会将对象作为String返回。它将调用String类上的toString方法,该类只返回自身。

答案 1 :(得分:1)

调用对象的方法时,调用的实际方法是对象的实际类型。这就是为什么实际调用的toString是String类方法。

BTW:泛型类型用于编译时,而不用于运行时。例如,您不能在同一个类2中使用以下方法: void foo(List l)和 void foo(List l)因为编译后两者都有相同的签名。

答案 2 :(得分:1)

实际上所有技巧都与泛型有关,即使你的代码片段展示了它。

它与 overriden 方法有关,toString()在超级超级类Object中定义,并在String类中覆盖,在运行时使用它们进行评估实际的对象类型而不是它的引用,即在调用时:

Object o = new String("hello");
o.toString(); // Here at runtime, the JVM will call the "hello" toString method and not the Object one.

在您的代码中,您已致电:

al.add("Hello World");

以上行执行以下操作:

  • 使用 Hello World 作为文字创建一个新的String对象,并将其添加到字符串池中。
  • 使列表中的第一个元素(索引0处的元素)引用该对象(即String 1)。

现在致电System.out.print(al.get(0));

  • 列表的第一个元素,即对Object对象的String引用,调用了他的toString()方法,并且如前所述将对对象实数类型进行评估,不是refence类型,即你将调用String#toString方法。