Java里把所有类型的数组也当作一个类来看待。
比如:
String[]
实际上是一个类。
数组类存在一个特点:
如果 A 是 B 的基类, 那么A[] 的引用可以指向 B[] 对象。
也就是说以下语句是合法的:
Object[] obArray = new String[2];
这种关系会产生一个代码隐患,如以下代码:
Object[] obArray = new String[2];
...
obArray[0] = new Integer(1);
编译阶段不会有任何错误,但是实际上是会有java.lang.ArrayStoreException异常抛出。
之所以会出现这个问题,是因为,一般在Java语言中左值的引用类型总是确定的,比如对于类似 a=b 这样的语句,a引用的类型一般总是确定的,编译阶段编译器检查b对象的类型是否与a引用类型相同或者是其派生类,如果不正确就会报编译错误。但是数组类的这一特性会隐藏了左值引用的实际类型。如例中所示,obArray[0]从代码上看似乎是Object类型的引用,但是实际上却是String类型的引用,这一点导致了该问题的产生。
实际上动态类型转换中也可能出现编译期正确,但是执行期出异常的情况,如 :
void fun(Object o)
{
String s = (String)o;
}
这里如果传入的参数o实际类型不是String会抛出强制类型转换异常。但这里的安全隐患实际上更容易被发现,因为单从这个语句就可以看出。而数组类的该特点所产生的安全隐患需要联系上下文才能判断出。显然以下代码咋一看基本看不出来有什么问题,但是却可能执行错误。
void fun(Object[] os)
{
if(os.length > 0)
os[0] = new Integer(1);
}