2011-02-04 14 views
32

Si tengo una instancia de Class, ¿hay alguna forma de obtener una instancia Class para su tipo de matriz? Lo que básicamente lo que estoy pidiendo es el equivalente de un método getArrayType que es la inversa del método getComponentType(), tal que:Obtención de la matriz Clase de un componente tipo

array.getClass().getComponentType().getArrayType() == array.getClass() 

Respuesta

43

Una cosa que viene a la mente es:

java.lang.reflect.Array.newInstance(componentType, 0).getClass(); 

Pero crea una instancia innecesaria.

Por cierto, esto parece funcionar:

Class clazz = Class.forName("[L" + componentType.getName() + ";"); 

Aquí está la prueba. Imprime true:

Integer[] ar = new Integer[1]; 
Class componentType = ar.getClass().getComponentType(); 
Class clazz = Class.forName("[L" + componentType.getName() + ";"); 

System.out.println(clazz == ar.getClass()); 

The documentation of Class#getName() define estrictamente el formato de nombres de clase de matriz:

Si esta clase de objeto representa una clase de matrices, a continuación, la forma interna del nombre consiste en el nombre de la tipo de elemento precedido por uno o más '[' caracteres que representan la profundidad de la matriz anidando.

El enfoque Class.forName(..) no va a trabajar directamente para las primitivas sin embargo - para ellos habría que crear una correlación entre el nombre (int) y la matriz abreviada - (I)

+0

Los primeros ve rsion (utilizando 'Array.newInstance (...). getClass()') * does * work for primitives. – finnw

+0

sí, mi punto era que el segundo no. – Bozho

+0

Esto es muy útil, gracias. Para mis propósitos, no necesito manipular primitivas, por lo que cualquiera de los enfoques es utilizable. –

6

Usted puede hacer lo siguiente

array.getClass() == 
    Array.newInstance(array.getClass().getComponentType(), 0).getClass() 

Por lo general, usted don' Necesito saber el tipo, solo quiere crear la matriz.

1

Otra posible refactorización es utilizar una superclase genérica y pasar en dos objetos de clase al constructor.

protected AbstractMetaProperty(Class<T> valueClass, Class<T[]> valueArrayClass) { 
    this.valueClass = valueClass; 
    this.valueArrayClass = valueArrayClass; 
} 

Luego, en subclases:

public IntegerClass() { 
    super(Integer.class, Integer[].class); 
} 

Luego, en la clase abstracta puede utilizar valueClass.cast(x), etc. valueArrayClass.isInstance(x)

9

En realidad, debido a ClassLoader, primitivas y matrices multidimensionales, la respuesta es un poco más complejo:

public static Class<?> getArrayClass(Class<?> componentType) throws ClassNotFoundException{ 
    ClassLoader classLoader = componentType.getClassLoader(); 
    String name; 
    if(componentType.isArray()){ 
     // just add a leading "[" 
     name = "["+componentType.getName(); 
    }else if(componentType == boolean.class){ 
     name = "[Z"; 
    }else if(componentType == byte.class){ 
     name = "[B"; 
    }else if(componentType == char.class){ 
     name = "[C"; 
    }else if(componentType == double.class){ 
     name = "[D"; 
    }else if(componentType == float.class){ 
     name = "[F"; 
    }else if(componentType == int.class){ 
     name = "[I"; 
    }else if(componentType == long.class){ 
     name = "[J"; 
    }else if(componentType == short.class){ 
     name = "[S"; 
    }else{ 
     // must be an object non-array class 
     name = "[L"+componentType.getName()+";"; 
    } 
    return classLoader != null ? classLoader.loadClass(name) : Class.forName(name); 
} 
+1

En la última línea, también puede usar el método forName con el parámetro del cargador de clases (que también funciona para 'null', evitando así la distinción entre mayúsculas y minúsculas). –

Cuestiones relacionadas