How to get the Array Class for a given Class in Java?

Viewed 9211

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this:

Class arrayOfFooClass = java.lang.reflect.Array.newInstance(fooClass, 0).getClass();

Is there a way to do this without creating the new instance?

5 Answers

You can get it using the class name. Just make sure you get the class using it's ClassLoader

    Class klass = yourClass;
    boolean init = wantToDoStaticOperations;
    Class.forName("[L" + klass.getName() + ";", init, klass.getClassLoader());

So, I for one, like fiddling with Strings. So, here's a more general solution that takes that approach, and still works with arbitrary class types. It is certainly more fiddly than your answer, but anyways, it's more complex to make it generic than the accepted answer gives it credit for, so here is the complete set of code to make it work:

    /**
     * Returns the name of the class, as the JVM would output it. For instance, for an int, "I" is returned, for an
     * array of Objects, "[Ljava/lang/Object;" is returned. If the input is null, null is returned.
     *
     * @param clazz
     * @return
     */
    public static String getJVMName(Class clazz) {
        if(clazz == null) {
            return null;
        }
        //For arrays, .getName() is fine.
        if(clazz.isArray()) {
            return clazz.getName().replace('.', '/');
        }
        if(clazz == boolean.class) {
            return "Z";
        } else if(clazz == byte.class) {
            return "B";
        } else if(clazz == short.class) {
            return "S";
        } else if(clazz == int.class) {
            return "I";
        } else if(clazz == long.class) {
            return "J";
        } else if(clazz == float.class) {
            return "F";
        } else if(clazz == double.class) {
            return "D";
        } else if(clazz == char.class) {
            return "C";
        } else {
            return "L" + clazz.getName().replace('.', '/') + ";";
        }
    }

    /**
     * Generically and dynamically returns the array class type for the given class type. The dynamic equivalent of
     * sending {@code String.class} and getting {@code String[].class}. Works with array types as well.
     * @param clazz The class to convert to an array type.
     * @return The array type of the input class.
     */
    public static Class<?> getArrayClassFromType(Class<?> clazz) {
        Objects.requireNonNull(clazz);
        try {
            return Class.forName("[" + getJVMName(clazz).replace('/', '.'));
        } catch(ClassNotFoundException ex) {
            // This cannot naturally happen, as we are simply creating an array type for a real type that has
            // clearly already been loaded.
            throw new NoClassDefFoundError(ex.getMessage());
        }
    }

Note that this is code from an existing library I wrote, which is why I make use of the getJVMName method. It could probably be modified to keep the dots instead of the /, but given that's how it works, I convert back and forth between the two methods. Anyhow, this works with any class, including nested array types.

Related