2013-05-09 17 views
9

Ich war gerade Java Reflection-API zu erkunden und ich gestoßen folgenden Code-SchnipselJava Reflection Snippet Ausgabe

public class Main { 
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException{ 
      Field value=Integer.class.getDeclaredField("value"); 
      value.setAccessible(true); 
      value.set(42, 43); 

      System.out.printf("six times seven %d%n",6*7); 
      System.out.printf("six times seven %d%n",42); 
      System.out.println(42); 
     } 
    } 

Ausgang:

six times seven 43 
six times seven 43 
42 

ich die Dokumentation der Set-Methode gelesen, die besagt, dass es legt Wert des Feldes für das gegebene Objekt. Aber ich bin nicht in der Lage, die Ausgabe des Codes zu verstehen, weil es in allen Fällen 42 drucken sollte.

Kann jemand bitte einen Einblick geben, was im Code passiert?

+1

http://www.dzone.com/snippets/reflection-integer-destroyer –

Antwort

4
 System.out.println(42); 

ruft println(int) nicht println(Object). Das Boxen passiert nie. Das macht es schneller und hat auch vor 1.5 funktioniert. In den anderen Fällen boxen Sie durch Integer.valueOf(int). Diese Methode ist so definiert, dass immer dieselben Integer Objekte für Werte zwischen -128 und einschließlich 127 zurückgegeben werden (möglicherweise für andere Werte dasselbe Verhalten). Also, wo 42 in Ihrem Programm eingeschlossen ist, erhalten Sie das gleiche Objekt, und wenn Sie den Wert value in diesem Objekt setzen, ändert es sich, egal welche Referenz gelesen wird.

Wenn Sie explizit in den Code in der Box setzen sind, es würde wie folgt aussehen:

 value.set(Integer.valueOf(42), 43); 

     System.out.printf("six times seven %d%n",Integer.valueOf(6*7)); 
     System.out.printf("six times seven %d%n",Integer.valueOf(42)); 
     System.out.println(42); 

Wie wir Integer.valueOf( kehren genau das gleiche Objekt für 42 wissen, ist der Code effektiv:

 Integer obj42 = Integer.valueOf(42); 

     value.set(Integer.valueOf(obj42, 43); 

     System.out.printf("six times seven %d%n", obj42); 
     System.out.printf("six times seven %d%n", obj42); 
     System.out.println(42); 
+0

Es ist wenig schwer zu begreifen. Können Sie mir bitte einen Hinweis geben wo finde ich weitere Details? – ankurtr

+0

@ ankur.trapasiya Von Boxen? Die Details finden Sie in der API-Dokumentation für 'Integer.valueOf' und in der JLS. –

+0

@ ankur.trapasiya [[Hier] (http://stackoverflow.com/questions/3130311/weird-java-boxing)] Sie haben interessante Fragen zum Boxen und Caching von ganzen Zahlen. Da 'printf (String format, Object ... args)' Objekte als Argumente benötigt, die in 'format' verwendet werden, wird Java autobox' int' auf 'Integer' setzen, aber da Sie den Wert von cached' Integer' von 42 auf 43 geändert haben, Dieser Wert wird gedruckt. 'println (int)' hat dieses Problem nicht, da es kein Boxing erfordert. Sie können auch versuchen 'System.out.printf (" sechs mal sieben% d% n ", neue Ganzzahl (6 * 7));' um neue Ganzzahl mit Wert 42 zu erzeugen, die nicht zwischengespeichert wird – Pshemo