Why does Java allow type-unsafe Array assignments?

怎甘沉沦 提交于 2019-11-30 05:07:01

I don't think there's an answer to this besides "legacy design". (Which I admit is a fancy way of saying "because".) You pretty much need to be able to do an equivalent of the last assignment you show somehow. (Otherwise you're stuck to making lots and lots of copies with manual up/down casts, assuming language features of Java pre 1.4)

In Java 1 when type semantics for arrays were basically set in stone, generics weren't available, or even up for consideration for a long while yet. So there was no mechanism available to express the higher-order type constraints needed to make this construct type-safe – and Gosling (IIRC a fan of simplicity) felt resolving this edge case of compile-time type safety wasn't worth complicated the language with whichever solutions were available. Or wasn't bothered by doing the check at runtime enough to even look for a solution. (At the end of the day language design decisions are arbitrary to at least some degree, and there's only one person that could answer this with any certainty.)

Firstly, I should point out that this is type-safe.

Object[] objects = new Integer[10];
objects[0] = "Hello World";

because an exception will be thrown. (It is not statically type-safe ... but that is a different statement entirely.)

The reason that Java allows this is historical. Until Java 5, Java did not support any form of generics. Gosling has said that if they had had the time to figure out and incorporate generics into Java 1.0, they would have done so.

Unfortunately, they didn't. But they still wanted to be able write things like a general purpose sort method with the following signature:

    void sort(Object[] array, Comparator comp) ...

To make this method work for any kind of object array (without generics), it was necessary to make arrays covariant; i.e. to make it legal to pass a String[] or Integer[] as an argument where the formal type is Object[]. If they hadn't done that you would have had to copy the String[] to an Object[], sort it, and then copy it back.

"Because it has to".

To elaborate a bit, consider the following example:

Object[] objects = null;
if (something) {
    objects = new Integer[10];
} else {
    objects = new String[10];
}

Now, how would the Java compiler know which assignments to allow and which to refuse? It can't. The compile-time type is Object so the compiler will let you put any Object in your array, simply because it doesn't have any knowledge of the runtime type of your array.

actually in case of arrays you get a exception at run time called ArrayStoreException when you add wrong type of element In this case a String. In case of generics there is no such exception. its for the very same reason you are not allowed to add anything but object, as you might just add a wrong type into the list.

There's Discussion that I found while I google it

I Found:

Firstly, arrays do not break type safety. If they did, then upcasting an array wouldn't fail at runtime. They make it impossible for the compiler to prove the program type-safe, so the checking is deferred until runtime.

I think confusion occurs here because one the one hand, since a String is-a Object an array of Strings is-obviously-an array of Objects, and on the other it clearly isn't. The answer is in the mutability of an array.

If the array is immutable, then it safe to treat a String[] as an Object[], because an immutable String[] is always exactly like an immutable Object[].

On the other hand, if the array is mutable, then it is not usually safe to treat a String[] as an Object[].

The "wildcards" technique described in the above link is exactly what CommonLisp has been doing for years.

(deftype StringArray? () (array String)) ; This is the type of arrays of String 
(deftype ObjectArray? () (array Object)) ; This is the type of arrays of Object 
(subtypep StringArray? ObjectArray?)      ; Is StringArray? a subtype of ObjectArray?? false, true                               ; No, it isn't. (false: it isn't, true: I'm ure) 
(deftype AnyArray? () (array *))         ; This is the type of arrays of anything (subtypep StringArray? AnyArray?)         ; Is StringArray? a subtype of AnyArray??   true, true                                ; Yes, it is. (true: it is, true: I'm sure)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!