2016-07-05 7 views
0

Ich weiß, es schlechtes Code-Design, sondern als temporären Hack ...Reflexionswerte zuzugreifen, die Klassen verschachtelt sind

Ich brauche eine private Karte zuzugreifen, in dem der Wert Initialisierungen einer statischen geschachtelten Klasse sind. Im folgenden Beispiel möchte ich auf jeden Wert von myMap von einem anderen Paket zugreifen.

package belongs.to.someone.else 

public class SOExample { 
    private Map<String, NestedClass> myMap; 

    static class NestedClass { 
     final int data; 
     NestedClass(final int data) { 
      this.data = data; 
     } 
    } 

    public void populateMyMap(){ 
     for(int i=0; i<100; i++){ 
      this.myMap.put(Integer.toString(i), new NestedClass(i)); 
     } 
    } 
} 

Aber ich scheine in ein Huhn-Ei-Problem zu laufen, wenn sie versuchen, den Zugang zu den SOExample.myMap Feld zu setzen. Ich bekomme "Fehler von außerhalb des Pakets" Fehler für die SOExample.NestedClass Werte in der letzten Anweisung.

package belongs.to.me 
public class SOExampleMyPackage { 
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
     SOExample example = new SOExample(); 
     example.populateMyMap(); 

     // Make the example.myMap field accessible 
     Field f = example.getClass().getDeclaredField("myMap"); 
     f.setAccessible(true); 
     // Next line throws error 
     Map<String, SOExample.NestedClass> myMapHere = (Map<String, SOExample.NestedClass>) f.get(example); 
    } 
} 

Ich freue mich über Ideen, wie Sie dieses Problem lösen können.

+0

Wie werden Sie 'myMapHere' verwenden? Der Compiler sagt Ihnen recht, dass Sie nicht über 'SOExample.NestedClass' auf' NestedClass' zugreifen können, da 'NestedClass' Paket-privat ist. – Pshemo

+0

Ist es möglich, dass 'NestedClass' tatsächlich eine öffentliche Schnittstelle implementiert, die Methoden enthält, an denen Sie interessiert sind? In diesem Fall könnten Sie 'Map ' oder 'Map '. – Pshemo

+0

@Pshemo myMap hat ungefähr 500.000 Werte, die durch eine sehr langsame diskrete Ereignissimulation erzeugt werden, die einen Tag zum Konvergieren benötigen kann. Wir möchten myMap serialisieren und diese Daten zur Hand haben, damit wir sie schnell deserialisieren können. – andrew

Antwort

1

Sie erhalten einen Kompilierzeitfehler, da auf die geschachtelte Klasse nicht zugegriffen werden kann.

Das einzige, was Sie tun können, ist mit Referenzen dieser Klasse zu vermeiden:

Field f = example.getClass().getDeclaredField("myMap"); 
f.setAccessible(true); 
Map map = (Map) f.get(example); 
Object obj = map.get("1"); 

Sie können Felder zugreifen und rufen Methoden auf der obj Instanz mit Reflexion.

0

@AdamSkywalker lieferte den richtigen Ansatz. Ich poste das letzte Arbeitsbeispiel nur der Vollständigkeit halber.

public class SOExampleMyPackage { 
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
     SOExample example = new SOExample(); 
     example.populateMyMap(); 

     // Make the example.myMap field accessible 
     Field f = example.getClass().getDeclaredField("myMap"); 
     f.setAccessible(true); 

     ///// 
     //SOLUTION start 
     ///// 
     Map<String, Object> myMapHere = (Map<String, Object>) f.get(example); 

     // Loop through entries and reflect out the values 
     Map<String, Integer> finalMap = new HashMap<String, Integer>(); 
     for (String k: myMapHere.keySet()){ 
      Field f2 = myMapHere.get(k).getClass().getDeclaredField("data"); 
      f2.setAccessible(true); 
      finalMap.put(k, (Integer) f2.get(myMapHere.get(k))); 
     } 
     ///// 
     //SOLUTION end 
     ///// 

     // Test it all 
     for (String k: finalMap.keySet()){ 
      System.out.println("Key: " + k + " Value: " + finalMap.get(k)); 
     } 
    } 
} 
Verwandte Themen