Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以取回一个“的对象”;“类型不正确”;从Java中的参数化列表中?_Java_Generics_Raw Types_Parameterized Types - Fatal编程技术网

为什么可以取回一个“的对象”;“类型不正确”;从Java中的参数化列表中?

为什么可以取回一个“的对象”;“类型不正确”;从Java中的参数化列表中?,java,generics,raw-types,parameterized-types,Java,Generics,Raw Types,Parameterized Types,下面是一段代码片段: import java.util.*; class Test { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); addToList(list); Integer i = list.get(0); //#1 fails at run-time String s

下面是一段代码片段:

import java.util.*;
class Test
{
    public static void main(String[] args)
    {
        List<Integer> list = new ArrayList<>();
        addToList(list);
        Integer i = list.get(0); //#1 fails at run-time
        String s = list.get(0); //#2 fails at compile-time
        list.get(0); //#3 works fine
        System.out.println(list.get(0)); //#4 works fine, prints "string"
    }
    static void addToList(List list){
        list.add("string");
    }
}
import java.util.*;
课堂测试
{
公共静态void main(字符串[]args)
{
列表=新的ArrayList();
地址列表(列表);
整数i=list.get(0);//#1在运行时失败
字符串s=list.get(0);//#2在编译时失败
list.get(0);/#3可以正常工作
System.out.println(list.get(0));//#4工作正常,打印“字符串”
}
静态无效添加列表(列表){
列表。添加(“字符串”);
}
}
我理解为什么可以在参数化列表中插入String类的对象

似乎我理解了为什么标有
#1
#2
的代码会失败


但是为什么
#3
#4
起作用呢?据我所知,编译器会在类型擦除后添加适当的强制转换,因此当我调用
list.get(0)
时,此方法应返回以前强制转换为整数的对象。那么,为什么在运行时在第3和第4个位置没有发生ClassCastException呢?

强制类型转换应用于
get
的返回类型,而不是引入污染的
add
。否则,您将在此时得到编译时错误或异常,因为您无法将
字符串
强制转换为
整数

,由于忽略了
get(int)
返回的对象,所以#3可以工作。将返回存储在位置
0
的内容,但由于没有强制转换,因此不会发生错误


#4工作正常的原因是相同的:由
get(0)
生成的对象被视为
java.lang.object
中的
println
子类,因为调用了
toString
。由于
toString()
可用于所有Java对象,因此调用将在没有错误的情况下完成。

首先,您可以向
列表添加字符串的原因。在方法中

static void addToList(List list){
您使用原始类型。原始类型的存在纯粹是为了与旧的Java版本兼容,不应在新代码中使用。在
addToList
方法中,Java编译器不知道
list
应该只包含整数,因此当向其添加字符串时,它不会抱怨

至于你们两人的不同行为
Integer i=list.get(0)
在编译时不会失败,因为Java认为
list
只包含
Integer
s。只有在运行时,
list
的第一个元素不是整数,因此您得到了一个
ClassCastException

String s=list.get(0)
在编译时失败,因为Java编译器假定
list
仅包含整数,因此它假定您尝试将整数分配给字符串引用

Just
list.get(0)
不存储方法调用的结果。因此,无论是在编译时还是在运行时,都没有任何失败的原因


最后,
System.out.println(list.get(0))
工作,因为
System.out
是一个
PrintStream
,并且有一个
println(Object)
方法,可以用
整型
参数调用该方法。

4:正在调用重载的System.out.println(Object),因为整数如果您查看
ArrayList#get
方法。这是:

public E get(int index) {
   //body
}
但在运行时,它实际上是:

public Object get(int index) {
       //body
}
所以当你做
整数i=list.get(0)
编译器将其转换为:

Integer i = (Integer)list.get(0);
现在在运行时,
list.get(0)
返回一个
对象
类型(实际上是
字符串
)。它现在尝试转换
String=>Integer
,但失败了

3. 因为它只是:

list.get(0)
编译器不会向任何内容添加类型转换。所以它只是,
list.get(0)

4.
list.get(0)
返回一个
对象
类型。所以调用PrintStream的
publicvidprintln(objectx)
方法


记住被调用而不是被调用。

抱歉,但是你似乎误解了这个问题。(顺便说一句,请随意修改你的答案,我将收回我的否决票。或者,如果你觉得其他答案足够,你可以删除它。)你的意思是,只有当我分配get(0)的结果时,才能转换为整数到某个变量?@fromSPb是的。除非将值指定给需要强制转换的对象,否则不会强制转换为整数。+1。JLS实际上没有规定“铸造”本身是发生的;相反,它指定如果实例的运行时类型与目标类型不匹配,则赋值转换()和方法调用转换()可以引发ClassCastException。OP的#3和#4不会触发这些规则中的任何一条,因此不存在ClassCastException。@dasblinkenlight感谢您的解释!因为并非所有的
列表
使用都已参数化:)
System.out.println(list.get(0));