0

I was trying to implement some kind of custom serialization with reflection, and then I found out that you just cannot cast A[] to B[] if A isn't a subtype of B even if all the elements in the array are subtypes of B (It should work because of type erasing because at the end of the day both a[] and b[] are Object[]).

here is an example of what I mean:

public class Foo {
    public static void main(String[] args) throws Exception {
        new Foo().testGenerics();
    }


    public LinkedList<String> strList;
    public String[] strArr;

    public void testGenerics() throws Exception {

        LinkedList<Object> objList = new LinkedList<Object>();
        objList.add("foo");


        Object[] objArr = new Object[1];
        objArr[0] = "bar";

        Foo.class.getField("strList").set(this, objList);

        System.out.println("list[0]  = " + strList.get(0));
        System.out.println("list len = " + strList.size());

        Foo.class.getField("strArr").set(this, objArr);

        System.out.println("arr[0]  = " + strArr[0]);
        System.out.println("arr len = " + strArr.length);

    }

}

In this example the list works fine but the array throws an exception at the line that tries to set it.

is there any reason arrays ignore type erasing, and is there any good way to create an array and a list for a given type at runtime?

2
  • 2
    "is there any reason arrays ignore type erasing" Because arrays are not generic. They are arrays... Commented May 22, 2020 at 13:45
  • 1
    The variable strArr is not defined generically - it is a String[]. So at runtime, you cannot assign an Object[] reference to that variable. The objList is just a List at runtime due to type-erasure. That's why you can use reflection to stick any List in there. Commented May 22, 2020 at 14:24

1 Answer 1

2

Arrays and generics are very different things. Generics are erased at runtime because the JVM doesn't know about them. However, the JVM does know about arrays. If you search in the JVM specification for "array", you'll see that section 3.9 is titled "Arrays". But you can't find anything about generics, or parameterised types. You can read section 3.9 in more detail to find out just how much the JVM knows about arrays. The Java Language Specification also talks about arrays and generics in very different sections.

Therefore, the JVM at runtime, can and does try to maintain the type safety of arrays, and stops you from assigning Object[] to String[]. This is analogous to the Java Compiler trying to maintain the type safety of LinkedLists at compile time by stopping you from assigning a LinkedList<Object> to a LinkedList<String>. It's not like the latter is somehow "safe to do" at runtime, it's just that the runtime doesn't know enough to stop you.

is there any good way to create an array and a list for a given type at runtime?

Given the Class<?> clazz and the length, you can create an array of it by:

Object o = Array.newInstance(clazz, length);

But having to do this smells like an XY problem... Make sure you know what you are doing.

You can create a list using the way you are using right now. It's not type safe, but that's a flaw of JVM/Java.

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

1 Comment

ah I see, Good to know that array are not generics, Ill look into that Array.newInstance it might be good enough if Ill find a way to extract the type of an array at runtime.

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.