2013-05-09 16 views
9

Stavo esplorando java riflessione API e ho incontrato seguente frammento di codiceJava Reflection uscita frammento

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); 
     } 
    } 

uscita:

six times seven 43 
six times seven 43 
42 

Ho letto la documentazione del metodo set che dichiara che imposta il valore del campo per l'oggetto dato. Ma non sono in grado di capire l'output del codice perché dovrebbe stampare 42 in tutti i casi.

Qualcuno può per favore dare una visione di ciò che sta accadendo nel codice?

+1

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

risposta

4
 System.out.println(42); 

sta chiamando println(int) non println(Object). Il pugilato non succede mai. Ciò lo rende più veloce e ha funzionato anche prima dell'1.5.

Negli altri casi, si sta utilizzando il Integer.valueOf(int). Questo metodo viene definito come sempre restituendo esattamente gli stessi oggetti Integer per valori compresi tra -128 e 127 (potrebbe avere o meno lo stesso comportamento per altri valori). Quindi, ogni volta che 42 viene inserito nel tuo programma, otterrai lo stesso oggetto e quando imposti il ​​valore di value in questo oggetto esso cambia indipendentemente dal riferimento a cui viene letto.

Se si dovesse mettere in boxe esplicitamente nel codice, sarebbe simile a questa:

 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); 

Come sappiamo Integer.valueOf( ritorna esattamente lo stesso oggetto per 42, il codice è efficace:

 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

È difficile da capire. Potete darmi qualche riferimento dove posso trovare maggiori dettagli? – ankurtr

+0

@ ankur.trapasiya del pugilato? I dettagli sono nei documenti API per 'Integer.valueOf' e in JLS. –

+0

@ ankur.trapasiya [[Qui] (http://stackoverflow.com/questions/3130311/weird-java-boxing)] hai domande interessanti sul box e sul caching Integers. Inoltre dal momento che 'printf (String format, Object ... args)' richiede gli oggetti come argomenti usati in 'format' Java autobox' int' a 'Integer', ma dato che hai cambiato il valore di' Integer' nella cache che rappresenta 42-43, questo valore verrà stampato. 'println (int)' non ha questo problema perché non richiede il pugilato. Puoi anche provare 'System.out.printf (" sei volte sette% d% n ", nuovo numero intero (6 * 7))' per creare un nuovo numero intero con valore 42 che non verrà memorizzato nella cache – Pshemo

Problemi correlati