Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Object[].class.isAssignableFrom(String[].class) == true?

Tags:

java

arrays

jvm

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?

like image 865
Brodie Avatar asked Dec 19 '25 08:12

Brodie


2 Answers

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 S and T are both reference types, then S[] >1 T[] iff S >1 T.
  • Object >1 Object[]
  • Cloneable >1 Object[]
  • java.io.Serializable >1 Object[]
  • If p is a primitive type, then:
    • Object >1 p[]
    • Cloneable >1 p[]
    • java.io.Serializable >1 p[]

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.

like image 125
Joachim Sauer Avatar answered Dec 21 '25 23:12

Joachim Sauer


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.

like image 27
mmx Avatar answered Dec 22 '25 00:12

mmx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!