2016-06-01 13 views
0

Ich versuche, eine HashMap<String, Number> über Reflexion zuzugreifen:Casting Zahl zu verdoppeln primitive

Serializable obj; //here goes the HashMap 
String name; 
... 
return (double)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name); 

aber bisher alles, was ich habe ist ein Gussfehler oben durch die Linie verursacht:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double 

Tat der Kennfeldwert, der durch den Schlüssel name zugegriffen wurde, war Integer .So ich die Zeile geändert haben:

return obj.getClass().getDeclaredMethod("get", Number.class).invoke(obj, name).doubleValue(); 

aber das hat auch nicht geklappt. Ich habe sogar doubleValue() unterstrichen als "undefiniert für den Typ Objekt" (aber warum Objekt, wenn ich Number.class habe?).

Ich bin mir nicht sicher, welche Casting-Regeln ich breche. Kann mir bitte jemand helfen, wenn meine Karteneinträge verschiedene Zahlenwerte haben (Integer, Float, Double) aber ich brauche die Methode, um einen double Wert (primitiv) zurückzugeben.

PS Es ist nicht wirklich ein Duplikat. Meine Frage ist allgemeiner. Aber danke für deine Anregungen. Ich habe vergessen, dass der Aufruf immer Objekt zurückgibt.

Der Arbeitscode lautet:

return ((Number)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name)).doubleValue(); 
+0

Was ist der Rückgabetyp von 'invoke'? Hat dieser Typ eine 'doubleValue' Methode? –

+1

Sie könnten einfach in "Integer" umwandeln und der Compiler wird dafür sorgen, dass die Konvertierung für Sie "doppelt" wird. Andernfalls wird nach "Integer" oder "Number" umgewandelt und dann die Methode "doubleValue" aufgerufen. –

+0

@Sotirios Delimanolis Der Rückgabetyp sollte Zahl sein, da ich versuche, das Number-Element von einer HashMap zu erhalten. Also sollte es eine DoubleValue-Methode haben. Der tatsächliche Wert des HashMap-Elements ist in diesem Fall Integer, wie ich zuvor geschrieben habe. – Vic

Antwort

0

Sie die falsche Annahme haben, dass es eine Beziehung zwischen dem Class Objekt war Sie getDeclaredMethod und der Rückgabetyp Method.invoke passieren. Die Class Objekte, die Sie an getMethod oder getDeclaredMethod übergeben, beschreiben den Parameter Typen der Methode, nicht den Rückgabetyp. Während Sie Argumente eines Untertyps des deklarierten Parametertyps übergeben können, müssen Sie genau den deklarierten Parametertyp angeben.

Der Parametertyp von Map.get ist Object, unveränderlich, so müssen Sie Object.class angeben, unabhängig davon, welche tatsächlichen Schlüssel, den Sie invoke passieren.

Desweiteren ist der reflektierende Rückgabetyp aufgrund der Typlöschung immer Object, unabhängig von der tatsächlichen Map Parametrisierung. Nicht, dass es wichtig ist, Method.invoke ist der erklärte Rückgabetyp immer Object, da verschiedene Method Instanzen verschiedene Methoden darstellen können. Wenn Sie einen HashMap<String, Number> haben, können Sie sich darauf verlassen, dass die zurückgegebenen Objekte Number Instanzen sind, aber nicht notwendigerweise Double Instanzen. Wie Sie erfahren haben, könnte es Integer Instanzen geben. Also, was Sie tun müssen, ist typgieße Number, gefolgt von doubleValue() Aufruf:

return ((Number)obj.getClass().getDeclaredMethod("get", Object.class) 
     .invoke(obj, name)).doubleValue(); 

Das heißt, wenn Sie wissen, dass das Objekt implementiert die Map Schnittstelle, gibt es keinen Grund, Reflexion zu verwenden überhaupt :

return ((Number)((Map<?,?>)obj).get(name)).doubleValue(); 

macht die Arbeit viel effizienter.

+0

Vielen Dank für eine sehr aufschlussreiche Antwort. – Vic