Domanda Codice Oggetto o = vero? new Integer (0): new Long (1) restituisce Long con valore 0. Perché? [duplicare]


Questa domanda ha già una risposta qui:

Si prega di considerare che abbiamo il codice qui sotto:

Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);

E il suo risultato è:

class java.lang.Long
value = 0

Invece di:

class java.lang.Integer
value = 0

Qualcuno potrebbe chiarire perché abbiamo tale funzionalità in Java? È molto strano per me Avete qualche esempio in cui questo può essere utile?

AGGIORNARE: Ecco un pezzo di bytecode, dove possiamo vedere, che cosa sta succedendo lì

NEW java/lang/Integer
DUP
LDC "0"
INVOKESPECIAL java/lang/Integer.<init> (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1

10
2017-11-28 13:04


origine


risposte:


Quello che sta succedendo qui è il risultato di

  • Promozione numerica binaria che trasforma il tuo Integer e Long digita long da utilizzare come tipo comune da applicare all'espressione dell'operatore condizionale
  • Unboxing di quegli oggetti wrapper
  • E poi inscatolare il valore risultante dell'espressione condizionale

Il secondo e il terzo operando dell'operatore condizionale devono avere lo stesso tipo, che è il tipo risultante dell'espressione. Integer e Long non sono, ovviamente, dello stesso tipo.

Tuttavia, come descritto in JLS§15.25, si applicherà il compilatore promozione numerica binaria quando si determina il possibile tipo comune da applicare all'espressione. Quella sezione ha la comoda Tabella 15.25-D che ci dice che quando il secondo operando è di tipo Integer e il terzo operando è di tipo Long, il compilatore farà promozione numerica binaria su Integer,Long. Promozione numerica binaria su Integer,Long i rendimenti long. Quindi il risultato dell'espressione dell'operatore condizionale è long.

Poiché il tipo di risultato dell'espressione è long, il Integer o Long dovrà essere unboxed (e quindi lanciato, nel caso di Integer).

Alla fine, lo assegni a un Object, che forza la boxe e avvolge il long in un Long. Quindi, si finisce con a Long contenente il valore 0, che corrisponde alla tua produzione.

Così efficacemente, se ignoriamo il fatto che il compilatore ottimizzerà la metà del seguente perché ha a che fare con un'espressione costante grazie al true nel codice (ho usato flag sotto invece), quel codice finisce per essere questo:

Object obj = Long.valueOf(flag ? (long)(new Integer(0)).intValue() : (new Long(1)).longValue());
System.out.println(obj.getClass() + "\nvalue = " + obj);
  • Il (long)(new Integer(0)).intValue() rappresenta unboxing il Integer e lanciandolo a long quindi corrisponde al tipo di risultato dell'espressione.
  • Il (new Long(1)).longValue() rappresenta unboxing il Long così esso corrisponde al tipo di risultato dell'espressione.
  • E il Long.valueOf rappresenta la boxe alla fine.

12
2017-11-28 13:10



Questo comportamento è ben spiegato nel JLS - 15.25. Operatore condizionale? ::

L'operatore condizionale ha tre espressioni di operando. ? appare tra il primo e secondo espressioni, e : appare tra il secondo e terzo espressioni.

[...]

Il tipo di un'espressione condizionale è determinato come segue:

  • [...]

  • Altrimenti, se il secondo e il terzo operando hanno tipi convertibili (§5.1.8) a tipi numerici, quindi ci sono diversi casi:

    • [...]

    • Altrimenti, promozione numerica binaria (§5.6.2) viene applicato ai tipi di operando e il tipo dell'espressione condizionale è il tipo promosso del secondo e del terzo operando.


4
2017-11-28 13:16



In realtà lungo può memorizzare il valore di un intero ma il numero intero non può memorizzare il valore di lungo (il concetto si allarga) e lo stai archiviando in Object, per questo lo sta archiviando in Long. internamente usa anche il pugilato e l'unboxing

Possibile codice del compilatore:

Long obj = true ? new Integer(0) : new Long(1);

System.out.println (obj.getClass () + "\ nvalue =" + obj);

Codice non funzionante (impossibile compilare):

 Integer obj = true ? new Integer(0) : new Long(1);

System.out.println (obj.getClass () + "\ nvalue =" + obj);

controlla da solo e fammi sapere se hai qualche dubbio in esso.


0
2017-11-28 13:10



Questo è legato a come funziona l'operatore ternario.

Gli operandi su entrambi i lati del : deve essere di tipi compatibili, quindi non puoi avere questo:

true ? 1 : "Hello"

Da int e String non possono essere convertiti implicitamente l'uno all'altro.

Nel tuo caso, tuttavia, i tipi siamo compatibile! Un int può essere convertito implicitamente in long. Ed è quello che ha fatto il compilatore! Ha visto un int e un lungo e decide che l'espressione dovrebbe valutare in a long. Annulla i due valori e converte implicitamente il int a a long. E infine, scatena il risultato long così diventa Long e mettilo nella variabile.


0
2017-11-28 13:22