3

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?

4 Answers 4

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

wow, where did you get the rules? can you give me a link? it seems String[] is subclass of Object[]. thank you a lot
No, String[] +is not a subclass+ of Object[]! That's what I'm saying all the time! It's a +subtype+, but that's a dfferent thing! I've had the links to the rules in my answer all the time, btw.
2

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.

2 Comments

The code you showed will throw an ArrayStoreException at runtime!
... or modify it based on objects of the base type, the purpose of polymorphism.
0

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);
    }
}

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.