2011-02-04 14 views
32

Se si dispone di un'istanza di Class, esiste un modo per ottenere un'istanza Class per il suo tipo di matrice? Quello che sto chiedendo in sostanza, è l'equivalente di un metodo getArrayType che è l'inverso del metodo getComponentType(), in modo tale che:Ottenere la matrice Classe di un tipo di componente

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

risposta

43

Una cosa che viene in mente è:

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

Ma crea un'istanza inutile.

Btw, questo sembra funzionare:

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

Ecco test. Esso stampa 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() definisce rigorosamente il formato dei nomi classe array:

Se questo oggetto classe rappresenta una classe di array, allora la forma interna del nome costituito dal nome del tipo di elemento preceduto da uno o più caratteri '[' che rappresentano la profondità del nesting dell'array.

L'approccio Class.forName(..) non lavorerà direttamente per primitive anche se - per loro che avrebbe dovuto creare una mappatura tra il nome (int) e la stenografia array - (I)

+0

Il primo ve rsion (usando 'Array.newInstance (...). getClass()') * fa * funziona per le primitive. – finnw

+0

sì, il mio punto era il secondo no. – Bozho

+0

Questo è molto utile, grazie. Per i miei scopi, non ho bisogno di gestire le primitive in modo che l'approccio sia utilizzabile. –

6

È possibile effettuare le seguenti

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

Di solito, si don' t necessario conoscere il tipo, vuoi solo creare l'array.

1

Un'altra possibile refactoring è usare una superclasse generica e passare in classe due oggetti al costruttore.

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

Poi in sottoclassi:

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

Poi nella classe astratta è possibile utilizzare valueClass.cast(x), valueArrayClass.isInstance(x) ecc

9

In realtà a causa di ClassLoader, primitive e array multidimensionali, la risposta è un po 'più complesso:

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

Nell'ultima riga, è anche possibile utilizzare il metodo forName con il parametro loader classe (che funziona anche per 'null', evitando così la distinzione tra maiuscole e minuscole). –

Problemi correlati