Why is Object[].class.isAssignableFrom(String[].class) == true, while String[].getSuperClass() or getGenericInterfaces() could not get Object[]?
I checked the source of JDK, but i don't think i can get the answer myself.
For now, I know JDK uses tree to store the relationship between Classes, and depth to indicate its level, Class::isAssignableFrom() searched the chain, so definately arrays are in that tree. and also String[] is connected to Object[].
Can i say that String[] is a subclass of Object[]?
Or is it just another weird thing of Java?
Class.isAssignableFrom() essentially checks the subtyping relation. "subtype" and "subclass" are two different concepts. The class hierarchy (i.e. subclassing) is only a part of subtyping.
Primitive types and array types have special cases for subtyping.
The rules for subtyping of array types are like this (note that ">1" means "is a directy subtype of"):
- If
SandTare both reference types, thenS[]>1T[]iffS>1T.Object>1Object[]Cloneable>1Object[]java.io.Serializable>1Object[]- If
pis a primitive type, then:
Object>1p[]Cloneable>1p[]java.io.Serializable>1p[]
The important part for your question is the very first item: an array type X[] is a subtype of an array type Y[] if and only if the component type X is a subtype of the component type Y.
Also note that strictly speaking neither Object[] nor String[] are classes. They are "only" types. While every class implicitly is a type, the reverse is not true. Another example of types that are not classes are the primitive types: boolean, byte, char, short, int, long, float and double are types, but they are not classes.
Another cause for confusion is the fact that you can easily get java.lang.Class objects representing those types. Again: This does not mean that those types are classes.
In Java (and .NET), arrays are covariant. It means you can pass an instance of type Apple[] to a method that expects a Fruit[] if Apple inherits Fruit. The following line is valid:
Fruit[] fruits = apples; // apples is an Apple[]
This means a Fruit[] is assignable from Apple[].
This is not very safe, of course. Assume:
void someMethod(Object[] objects) {
objects[0] = "Hello World"; // throws at run time.
}
void test() {
Integer[] integers = new Integer[10];
integers[0] = 42;
someMethod(integers); // compiles fine.
}
This design decision is handy when you want to use arrays contents (e.g. print it) but not modify it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With