开发者

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

Why is Object[].class.isAssignableFrom(String[].class) == true, while String[].getSuperClass() or getGenericInterfaces() could开发者_JS百科 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 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.


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.


Because String[] can actually be converted/widened to Object[].

You might be thinking that this tests if String[] is assignable from Object[], but it actually tests the reverse (if String[] can be assigned to Object[]).

This code compiles and executes as expected:

public static void main(String[] args) {
    String[] strings = new String[]{ "hello", "world" };
    printArray(strings);
}

public static void printArray(Object[] array) {
    for (Object obj : array) {
        System.out.println(obj);
    }
}


If this object represents an array class then the Class object representing the Object class is returned.link

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜