57 Stimmen

Java Reflection ruft Konstruktor mit primitiven Typen auf

Ich habe eine Methode in meinem Test-Framework, die abhängig von den übergebenen Parametern eine Instanz einer Klasse erzeugt:

public void test(Object... constructorArgs) throws Exception {
    Constructor<T> con;
    if (constructorArgs.length > 0) {
        Class<?>[] parameterTypes = new Class<?>[constructorArgs.length];
        for (int i = 0; i < constructorArgs.length; i++) {
            parameterTypes[i] = constructorArgs[i].getClass();  
        }
        con = clazz.getConstructor(parameterTypes);
    } else {
        con = clazz.getConstructor();
    }
}

Das Problem ist, dass dies nicht funktioniert, wenn der Konstruktor primitive Typen hat, wie folgt:

public Range(String name, int lowerBound, int upperBound) { ... }

.test("a", 1, 3);

Ergebnisse in:

java.lang.NoSuchMethodException: Range.<init>(java.lang.String, java.lang.Integer, java.lang.Integer)

Die primitiven Ints werden automatisch in Objektversionen umgewandelt, aber wie bekomme ich sie für den Aufruf des Konstruktors zurück?

160voto

Andrzej Doyle Punkte 99892

使用する Integer.TYPE anstelle von Integer.class .

Gemäß der Javadocs ist dies "Die Klasseninstanz, die den primitiven Typ repräsentiert int ."

Sie können auch Folgendes verwenden int.class . Es ist eine Abkürzung für Integer.TYPE . Nicht nur Klassen, auch für primitive Typen kann man sagen type.class in Java.

21voto

Plaudit Design Punkte 1158

Um primitive Typen zu referenzieren, verwenden Sie zum Beispiel:

Integer.TYPE;

Sie müssen wissen, welche Argumente, die an Ihre Methode übergeben werden, primitive Werte sind. Sie können dies mit tun:

object.getClass().isPrimitive()

7voto

Jake Punkte 61

Da die primitiven Typen autoboxed sind, wird die getConstructor(java.lang.Class<?>... parameterTypes) Anruf scheitert. Sie müssen manuell eine Schleife durch die verfügbaren Konstruktoren ziehen. Wenn alle Typen übereinstimmen, ist alles in Ordnung. Wenn einige Typen nicht übereinstimmen, aber der erforderliche Typ eine Primitive ist UND der verfügbare Typ die entsprechende Wrapper-Klasse ist, dann können Sie diesen Konstruktor verwenden. Siehe unten:

static <C> Constructor<C> getAppropriateConstructor(Class<C> c, Object[] initArgs){
    if(initArgs == null)
        initArgs = new Object[0];
    for(Constructor con : c.getDeclaredConstructors()){
        Class[] types = con.getParameterTypes();
        if(types.length!=initArgs.length)
            continue;
        boolean match = true;
        for(int i = 0; i < types.length; i++){
            Class need = types[i], got = initArgs[i].getClass();
            if(!need.isAssignableFrom(got)){
                if(need.isPrimitive()){
                    match = (int.class.equals(need) && Integer.class.equals(got))
                    || (long.class.equals(need) && Long.class.equals(got))
                    || (char.class.equals(need) && Character.class.equals(got))
                    || (short.class.equals(need) && Short.class.equals(got))
                    || (boolean.class.equals(need) && Boolean.class.equals(got))
                    || (byte.class.equals(need) && Byte.class.equals(got));
                }else{
                    match = false;
                }
            }
            if(!match)
                break;
        }
        if(match)
            return con;
    }
    throw new IllegalArgumentException("Cannot find an appropriate constructor for class " + c + " and arguments " + Arrays.toString(initArgs));
}

6voto

user3896501 Punkte 2802

Können Sie schreiben

int[].class.getComponentType()

ou

Integer.TYPE

ou

int.class

2voto

Nikita Rybak Punkte 66202

Wenn primitiv int Wert wird automatisch in Integer Objekt ist es nicht mehr primitiv. Sie können nicht erkennen, ob Integer Beispiel, ob es sich um int zu einem bestimmten Zeitpunkt.

Ich würde vorschlagen, zwei Arrays in test Methode: eine mit Typen und eine mit Werten. Es beseitigt auch die Mehrdeutigkeit, wenn Sie einen Konstruktor haben MyClass(Object) und übergeben Sie einen String-Wert ( getConstructor suchen würde String Konstrukteur).
Außerdem kann man den erwarteten Parametertyp nicht erkennen, wenn der Parameterwert Null ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X