Newsgroup: it.comp.java
Titolo: Comparazione e template (e` un baco o che?)

Posto che non uso Java da molto (se non perche` sono obbligato in
universita` :P) e quindi non mi sono aggiornato sul funzionamento
interno dei tipi parametrici aggiunti nella 1.5 o 5 a dir si voglia. Mi
e` stato fatto notare questo esempietto:
public class Test
{
    static <T> void foo(T a, T b)
    {
        System.out.println(a + ": " + (a == b));
    }
    public static void main(String[] args)
    {
        for (int i = -200; i<201; ++i)
            foo(i, i);
    }
}
il quale stampa una serie di false e true in maniera non randomica ma
senza logica spiegazione (almeno per me). Che succede? E` un baco? Mi
sono perso qualcosa negli internals di Java (puo` darsi sicuramente :))
Lawrence

 }
in foo(i,i) Java converte gli int in Integer, quindi a priori dovrebbe
darti tutti false..
Però mi sembra che Integer mantenga una sorta di cache, in modo che
valueOf(int i) ritorni un oggetto già esistente. questo spiega i true.
-- 
Pietro
(\_/)  <- This is Bunny.
(°_°)     Copy Bunny into your signature to help
(> <)     him on his way to world domination.

mi e` stato detto altrove che e` un baco noto invece :)

 
Posta il link

 senza logica spiegazione (almeno per me). 
Il range di valori per cui restituisce true è quello del byte (da -128 a 
127); probabilmente per motivi di ottimizzazione con questi valori viene 
utilizzato un meccanismo di internalizzazione simile a quello delle 
stringhe. Ecco il pezzo di sorgente di java.lang.Integer che spiega 
questo fatto:
     /**
      * Returns a <tt>Integer</tt> instance representing the specified
      * <tt>int</tt> value.
      * If a new <tt>Integer</tt> instance is not required, this method
      * should generally be used in preference to the constructor
      * {@link #Integer(int)}, as this method is likely to yield
      * significantly better space and time performance by caching
      * frequently requested values.
      *
      * @param  i an <code>int</code> value.
      * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
      * @since  1.5
      */
     public static Integer valueOf(int i) {
	final int offset = 128;
	if (i >= -128 && i <= 127) { // must cache
	    return IntegerCache.cache[i + offset];
	}
         return new Integer(i);
     }
Che succede? E` un baco?
Non credo, perché lo fosse dovrebbe essere garantito nelle specifiche 
che ad int uguale corrisponda stessa istanza di Integer, e a memoria non 
mi sembra che sia il comportamento tipico dei wrapper.
Cmq interessante osservazione.
Ciao :)
pole
-- 
ammentos - a lightweight persistence framework for JDK5
http://ammentos.biobytes.it
Flash tutorial: 
http://ammentos.biobytes.it/quickstart/quickstart.htm

         System.out.println(a + ": " + (a == b));
[cut]
Perche' non viene usato
System.out.println(a + ": " + a.equals(b));
?
--
Marco
*** Posted via a free Usenet account from 
http://www.teranews.com
 ***

http://groups.google.com/group/it.comp.os.dibattiti/msg/c9db99882f207c40

non saprei, forse per evidenziare il problema anche perchè equals
ovviamente funziona correttamente :)

 
Fosse anche un baco del compilatore o del linguaggio, cosa che non
credo, per il codice che hai scritto è giusto che sia così!
(T a) e (T b) sono Object, a run-time ottieni:
static void foo(Object a, Object b) { ... }
in quanto i generic esistono solo quando scrivi e vengono cancellati in
compilazione.
Detto questo tu stai facendo = tra due Object, cioè confronti gli
indirizzi, ed è giusto che tu, tra due Integer ottenga true e false a
seconda se la classe utilizza o no il cache.
Se poi tu in realtà confronti interi.. Java non lo sa perché tu gli
passi oggetti.
Vuoi avere tutti true? Utilizza equals().
Non credo sia un baco ma il giusto comportamento che deve avere la
classe Integer utilizzano questo meccanismo di cache

ovviamente funziona correttamente :)
Leggendo il post dell'autore dell'esempio ho dedotto che ha
collassato in un unico metodo altri che prima erano distinti.
I metodi originali erano scritti in modo simile (==), e riunendoli
e' saltato fuori il problema. Scrivere del codice 'generificato'
richiede una certa perizia, ecco la ragione della mia domanda.
Rimanendo nel campo degli esempi spiazzanti il mio preferito e'
questo:
http://www.davidflanagan.com/blog/000022.html
public class Equality {
    public static void main(String[] args) {
        Integer i = new Integer(0), j = new Integer(0);
        // The two objects are both equal to 0
        System.out.println(i == 0 && j == 0);
        // But they are not equal to each other
        System.out.println(i == j);
        // true: relational ops unbox both sides
        System.out.println(i <= j && i >= j);
}
Qui veramente il linguaggio sempra pensato per far cadere
nella trappola i programmatori alle prime armi.
