Sono tipi primitivi differenti in Java e C #?
-
22-09-2019 - |
Domanda
I sono la conversione manualmente il codice da Java a C # e alle prese con (quello che io chiamo) tipi primitivi (vedi, ad esempio, fare autoboxing e si comportano in modo diverso unboxing in Java e C # ). Dalle risposte ho capito che double
(C #) e Double
(C #) sono equivalenti e double
(C #) può essere utilizzato anche in contenitori, per esempio come una chiave in un dizionario. Tuttavia, double
(Java) non può essere utilizzato in contenitori come HashMap è per questo che è auto-boxed a Double
(Java).
- È
double
(C #), un primitivo o di un oggetto? - Se si tratta di una primitiva ciò che lo rende si comportano diversamente da
double
(Java)?
double
(C #) non può essere impostato su null a meno che non si è fatto nullable
.
- È
double?
(C #) equivalente aDouble
(Java)? Sono entrambi indicati come oggetti?
(è l'uso del termine "oggetto di prima classe" utile in questa discussione?)
Soluzione
Sia C # e Java hanno tipi primitivi (o "valore"): int, double, float, ecc ...
Tuttavia, dopo questo C # e Java tendono a dividere.
Java ha tipi classe wrapper per tutti i tipi primitivi (che è un piccolo insieme finito in Java) che permette loro di essere trattati come oggetti.
double/Double
, int/Integer
, bool/Boolean
, ecc Questi tipi di involucro sono riferimento tipi (leggi: classi) e, come tali, null
è un valore valido per assegnare a tali espressioni / variabili tipizzate. Le versioni recenti di Java (1.5 / 5 +) aggiungere in coercizioni impliciti dalle primitive per il loro involucro corrispondente.
// Java
Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
Boolean b = null; // okay, can assign null to a reference type
boolean n = null; // WRONG - null is not a boolean!
C # non fornisce un un involucro così diretta 1 - in parte, perché C # supporta un insieme infinito di tipi di valore via strutture ; piuttosto, C # gestisce "tipi di valore nullable" con l'introduzione di un Nullable<T>
tipo involucro. Inoltre C #, come Java, ha conversioni implicite dal tipo di valore T
a Nullable<T>
, con la restrizione che T "non è un tipo nullable" stesso.
// C#
Nullable<bool> b = true; // implicit conversion bool -> bool?
bool? b = true; // short type syntax, implicit conversion
bool? b = null; // okay, can assign null as a Nullable-type
bool b = null; // WRONG - null is not a bool
Si noti che Nullable<T>
è anche un tipo di valore e quindi segue le regole di struttura standard per quando / se un valore è "in pila" o meno.
In risposta al commento:
Assolutamente corretto, Nullable è un valore di tipo non permettono di avere un consumo di memoria più compatto in taluni casi come si può evitare il sovraccarico della memoria di un tipo di riferimento: Qual è l'occupazione di memoria di un Nullable
// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true
L'articolo Java Suggerimento 130: Sai i dati dimensioni? parla circa il consumo di memoria tipo di riferimento (in Java). Una cosa da notare è che la JVM è specializzata versioni di array interno, uno per ogni tipo primitivo e per gli oggetti (tuttavia, si prega di notare che questo articolo contiene alcune dichiarazioni fuorvianti ). Si noti come gli oggetti (vs. primitive) incorrono in testa memoria aggiuntiva e le problematiche di allineamento di byte. C # tuttavia, può estendere il caso ottimizzato-array per tipi Nullable<T>
contro le limitate le speciali vetrine JVM contiene perché Nullable<T>
è essa stessa solo un tipo di struttura (o "primitiva").
Tuttavia, un oggetto, richiede solo una piccola dimensione fissa per mantenere un "riferimento" ad esso in una fessura variabile. Una slot variabile di tipo Nullable<LargeStruct>
invece, deve avere spazio per LargeStruct+Nullable
(fessura stessa può essere sul mucchio). Vedere C # Concetti: Valore vs tipi di riferimento . Si noti come nell'esempio "lifting" al di sopra della variabile è di tipo object
:. object
è il "tipo root" in C # (genitore di entrambi i tipi di riferimento e tipi di valore) e non un tipo di valore specializzata
1 Il linguaggio C # supporta un insieme fisso di alias per i tipi primitivi / comuni che consentono l'accesso ai nomi tipo "amichevole minuscole". Ad esempio, double
è un alias per System.Double
e int
è un alias per System.Int32
. A meno che un diverso tipo Double
è importata portata, double
e Double
faranno riferimento allo stesso tipo in C #. Mi consiglia di utilizzare gli alias a meno che non ci sia una ragione per fare altrimenti.
Altri suggerimenti
Nullable<double>
(aka double?
) in C # è non la stessa di un Double
in Java.
Prima di Java aveva autoboxing / unboxing, si doveva convertire manualmente tra le primitive e oggetti di prima classe:
Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();
In Java 1.5 che ha cambiato, quindi si può solo fare:
Double dblObj = 2.0;
double dblPrim = dblObj;
E Java sarebbe inserire il codice per rispecchiare l'esempio di cui sopra automaticamente.
C # è diverso perché c'è un numero illimitato di tipi "primitivi" (quello che le chiamate CLR tipi di valore ). Questi si comportano per lo più come primitivi di Java, utilizzando semantica di valore . È possibile creare nuovi tipi di valore utilizzando la parola chiave struct
. C # ha autoboxing / unboxing per tutti tipi di valore, e rende anche tutti i tipi di valore derivano da Object
.
Quindi, è possibile utilizzare un tipo di valore (come double
) in cui si desidera utilizzare alcun riferimento a un oggetto (ad esempio come una chiave in una Dictionary
) e sarà in scatola, se necessario, o semplicemente utilizzato direttamente. (Implementazione C # 's Generics è abbastanza buono per evitare di boxe nella maggior parte dei casi).
In C #, il modo migliore per separare gli oggetti sono da "Tipi di valore", che sono un po 'come primitivi - int
s, bool
s, ecc e "tipi di riferimento." - classi etc