为什么在Java中将整数添加到字符串数组中不会生成编译错误?
为什么我试图向Java数组中添加一个为什么在Java中将整数添加到字符串数组中不会生成编译错误?,java,Java,为什么我试图向Java数组中添加一个整数,该数组声明为对象[],但实例化为字符串[],却没有生成编译错误 Object[] ob = new String[1]; ob[0] = new Integer(1); // this shouldn’t compile but it does! 当我运行这个程序时,我会得到一个运行时异常,而不是一个(更可取的)编译时错误!这是正确的行为吗?我不应该得到编译时错误吗?这是Java设计人员做出的选择:String[]扩展了Object[],但是在没有运行
整数
,该数组声明为对象[]
,但实例化为字符串[]
,却没有生成编译错误
Object[] ob = new String[1];
ob[0] = new Integer(1); // this shouldn’t compile but it does!
当我运行这个程序时,我会得到一个运行时异常,而不是一个(更可取的)编译时错误!这是正确的行为吗?我不应该得到编译时错误吗?这是Java设计人员做出的选择:
String[]
扩展了Object[]
,但是在没有运行时异常的情况下,不能向具体类型为String[]
的数组中添加任何内容
他们可能会使以下内容无效:
Object[] ob = new String[1];
因为它可以有效地将任何类型的对象添加到数组中,而不会出现任何编译器错误(如您所注意到的),这是完全正常的,因为整数是一个对象,数组的编译时类型是object[]
他们没有对数组进行选择,但对一般集合进行了选择:
List<Object> ob = new ArrayList<String>();
List ob=new ArrayList();
生成编译器错误,因为
List
未扩展List
。集合通常应该优先于数组,因为它们更安全,并且提供了更多的功能。这是Java设计师做出的选择:String[]
扩展了对象[]
,但是除了字符串
之外,不能向具体类型为String[]的数组添加任何内容
而不获取运行时异常
他们可能会使以下内容无效:
Object[] ob = new String[1];
因为它可以有效地将任何类型的对象添加到数组中,而不会出现任何编译器错误(如您所注意到的),这是完全正常的,因为整数是一个对象,数组的编译时类型是object[]
他们没有对数组进行选择,但对一般集合进行了选择:
List<Object> ob = new ArrayList<String>();
List ob=new ArrayList();
生成编译器错误,因为
List
未扩展List
。集合通常比数组更安全,并提供更多的功能。您可能需要考虑的主要问题是引用数组的运行时类型(String[]
)与数组变量的编译时类型(Object[]
)。编译器只强制您放入数组的内容与引用它的数组变量的静态类型兼容。这个例子突出了这一点:
String[] strs = new String[1];
Object[] objs = strs;
strs[0] = new Integer(1); /* error, says the compiler! */
objs[0] = new Integer(1); /* fine by me, says the compiler! */
现在,您应该合理地感到不安的实际上是您的第一行:
Object[]ob=newstring[1]
,这意味着字符串[]
与对象[]
的赋值兼容,换句话说,就是它的子类型。这与CS的众所周知的事实相反,即容器类型在其元素的类型上是相反的。为什么Java不是这样?我曾经读过一篇文章,其中James Gosling被问到这一点,他回答说他们知道事实,但希望Java方法能够接受任何类型的数组(通过对象[]
类型)。这源于Java需要成为“蓝领语言”,而不是进入类型理论的精确性,这会给他们带来心理负担。见证泛型“您可能需要考虑的要点是引用数组的运行时类型(字符串[]
)与数组变量的编译时类型(对象[]
)。编译器只强制您放入数组的内容与引用它的数组变量的静态类型兼容。这个例子突出了这一点:
String[] strs = new String[1];
Object[] objs = strs;
strs[0] = new Integer(1); /* error, says the compiler! */
objs[0] = new Integer(1); /* fine by me, says the compiler! */
现在,您应该合理地感到不安的实际上是您的第一行:Object[]ob=newstring[1]
,这意味着字符串[]
与对象[]
的赋值兼容,换句话说,就是它的子类型。这与CS的众所周知的事实相反,即容器类型在其元素的类型上是相反的。为什么Java不是这样?我曾经读过一篇文章,其中James Gosling被问到这一点,他回答说他们知道事实,但希望Java方法能够接受任何类型的数组(通过对象[]
类型)。这源于Java需要成为“蓝领语言”,而不是进入类型理论的精确性,这会给他们带来心理负担。见证泛型“ob
是一个对象[]
<代码>整数
是对象
的子类。所以这应该是非常好的。也许你想声明“代码> OB<代码>为<代码> String []/Cord>而不是.HovirCRAFFTPulfEOLS,你所说的写得不好的代码是真的,但是在其他语言中,C++想到的是你被编译器保护,不写这种废话。这只是一个简单的例子。在现实世界的程序中,您不可能同时看到所有代码。你怎么知道你是否将正确的类型分配给了正确的容器?@smallB:我不知道答案,除了将变量声明为可能的最一般类型,但不知道更多。我不明白为什么这个问题被关闭。这是一个关于Java语义陷阱的完全合理的问题。可能让您感到困惑的要点是引用数组的运行时类型(String[]
)与数组变量的编译时类型(Object[]
)。编译器只强制您输入数组的内容与引用它的数组变量的静态类型兼容。我同意@Marko,这是一个关于Java的有效问题,澄清这些原则只能帮助我们所有人,我已投票重新打开并投票表决该问题。我认为关闭这个的唯一原因是