Les types primitifs sont-ils différents en Java et en C#?
je suis en train de convertir manuellement du code de Java en C# et j'ai du mal avec les types primitifs (ce que j'appelle) (voir, par exemple est-ce que l'autoboxing et le unboxing se comportent différemment en Java et C# ). D'après les réponses, je comprends que double
(C#) et Double
(C#) sont équivalents et double
(C#) peut également être utilisé dans des conteneurs, par exemple comme une clé dans un dictionnaire. Cependant, double
(Java) ne peut pas être utilisé dans des conteneurs comme HashMap, c'est pourquoi il est Double
(Java).
- Est
double
(C#), un primitif ou d'un objet? - si c'est une primitive, qu'est-ce qui la fait se comporter différemment de
double
(Java)?
double
(C#) ne peut pas être défini à null à moins qu'il ne soit fait nullable
.
- Est
double?
(C#) équivalent àDouble
(Java)? Les deux sont-ils appelés objets?
(L'utilisation du terme "objet de première classe" est-elle utile dans cette discussion?)
3 réponses
les types C# et Java sont primitifs (ou" value"): int, double, float, etc...
cependant, après CE C# et Java ont tendance à se diviser.
Java a des types de classe wrapper pour tous les types primitifs (qui est un petit ensemble fini en Java) qui permet de les traiter comme objet.
double/Double
, int/Integer
, bool/Boolean
, etc. Ces types d'enrubannage sont des types de référence (Lire: Classes) et, en tant que tels, null
est une valeur valide à attribuer à de telles expressions/variables dactylographiées. Les versions récentes de Java (1.5 / 5+) ajoutent des coercions implicites des primitifs à leur enveloppe correspondante.
// 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# n'est pas un tel direct emballage 1 - en partie, parce que le C# prend en charge un ensemble infini de types de valeur via structures ; au contraire, C# poignées "nullable types de valeur" par l'introduction d'une Nullable<T>
wrapper type. En outre, c#, comme Java, a des conversions implicites du type de valeur T
à Nullable<T>
, avec la restriction que T est" non nullable type " lui-même.
// 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
notez que Nullable<T>
est aussi un type de valeur et suit donc les règles de structure standard pour quand/si une valeur est" sur la pile " ou non.
en réponse au commentaire:
Absolument correct, Nullable être une valeur de type ne lui permettent de disposer d'un plus compact de la mémoire dans certains cas comme on peut éviter la surcharge de la mémoire d'un type de référence: qu'est-Ce que l'empreinte mémoire d'un Nullable
// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true
L'article Java Astuce 130: connaissez-vous vos données? parle de la consommation de mémoire de type de référence (en Java). Une chose à noter est que le JVM a des versions spécialisées de tableaux en interne, une pour chaque type primitif et pour les objets (cependant, s'il vous plaît noter que cet article contient certains déclarations trompeuses ). Notez comment les objets (vs. primitives) encourent une mémoire supplémentaire et les problèmes d'alignement des octets. C# peut cependant étendre le cas du tableau optimisé pour les types Nullable<T>
par rapport aux cas spéciaux limités de la JVM parce que Nullable<T>
est lui-même juste un type de structure (ou "primitif").
cependant, un objet, nécessite seulement une petite taille fixe pour maintenir une "référence" à lui dans une fente variable. Une fente variable de tapez Nullable<LargeStruct>
, d'autre part, doit avoir de l'espace pour LargeStruct+Nullable
(la fente elle-même peut être sur le tas). Voir C# Concepts: Valeur vs Types de Référence . Notez que dans l'exemple" lifting "ci-dessus, la variable est de type object
: object
est le" type racine "en C# (parent à la fois des types de référence et des types de valeur) et et non un type de valeur spécialisée.
1 le langage C# supporte un ensemble fixe de alias pour les types primitifs/communs qui permettent l'accès aux noms de type" friendly lowercase". Par exemple, double
est un alias pour System.Double
et int
est un alias pour System.Int32
. À moins qu'un type différent de Double
ne soit importé dans la portée, double
et Double
feront référence au même type dans le numéro C. Je recommande d'utiliser les alias sauf s'il y a une raison de faire autrement.
Nullable<double>
(aka double?
) en C# est pas même comme un Double
en Java.
avant que Java n'ait l'autoboxing/ unboxing, vous avez dû convertir manuellement entre les primitives et les objets de première classe:
Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();
en Java 1.5 qui a changé, donc vous pouvez juste faire:
Double dblObj = 2.0;
double dblPrim = dblObj;
et Java insérerait le code pour refléter l'exemple ci-dessus automatiquement.
C# est différent parce qu'il y a un nombre illimité de types "primitifs" (ce que le CLR appelle types de valeur ). Ceux-ci se comportent principalement comme les primitives de Java, en utilisant valeur sémantique . Vous pouvez créer de nouveaux types de valeur en utilisant le mot-clé struct
. C # possède des types de valeurs tous et fait dériver tous les types de valeurs de Object
.
de Sorte que vous pouvez utiliser un type de valeur (comme double
) où vous utiliseriez n'importe quelle référence d'objet (par exemple comme une clé dans un Dictionary
) et il sera encadré si nécessaire, ou bien simplement utilisé directement. (La mise en oeuvre des génériques de c#est assez bonne pour éviter la boxe dans la plupart des circonstances.)
dans C#, la meilleure façon de séparer les objets est par "types de valeur" qui sont un peu comme les primitives - int
s, bool
s, etc et "Types de référence" - classes etc.