Java と C# ではプリミティブ型は異なりますか?
-
22-09-2019 - |
質問
私は手動でコードをJavaからC#に変換しており、(私が呼んでいる)プリミティブ型に苦労しています(たとえば、 オートボックス化とボックス化解除は Java と C# で異なる動作をしますか?)。回答から分かるのですが、 double
(C#) と Double
(C#) は同等であり、 double
(C#) はコンテナーでも使用できます。辞書のキーとして。しかし、 double
(Java) は HashMap のようなコンテナでは使用できないため、自動的にボックス化されます。 Double
(ジャワ)。
- は
double
(C#) プリミティブですか、それともオブジェクトですか? - それがプリミティブの場合、何が異なる動作をするのか
double
(ジャワ)?
double
(C#) を作成しない限り null に設定することはできません nullable
.
- は
double?
(C#) と同等Double
(ジャワ)?両方ともオブジェクトと呼ばれますか?
(この議論では「ファーストクラス オブジェクト」という用語の使用が役に立ちますか?)
解決
C# と Java の両方にプリミティブ (または「値」) 型があります。int、double、floatなど...
しかし、この後はC#とJavaが分かれる傾向にあります。
Javaにはラッパークラスタイプがあります。 すべてのプリミティブ型 (これは Java の小さな有限セットです) これにより、それらをオブジェクトとして扱うことができます。double/Double
, int/Integer
, bool/Boolean
, 、など。これらのラッパー型は参照型です (以下を参照)。クラス)、そしてそれ自体、 null
は、そのような型付き式/変数に割り当てる有効な値です。Java の最近のバージョン (1.5/5+) では、プリミティブから対応するラッパーへの暗黙的な強制が追加されています。
// 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# ではそのような直接的なラッピングは提供されません1 - 部分的には、C# がサポートしているためです。 値の型の無限のセット 経由 構造物;むしろ、C# は、 Nullable<T>
ラッパータイプ。さらに、C# には Java と同様に、値の型からの暗黙的な変換があります。 T
に Nullable<T>
, ただし、T 自体は「null 許容型ではない」という制限があります。
// 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
ご了承ください Nullable<T>
も値型であるため、値が「スタック上」にあるかどうかについての標準構造規則に従います。
コメントへの返信:
まったくその通りです。Nullable は値型であるため、メモリ使用量をよりコンパクトにできます。 場合によっては 参照型のメモリ オーバーヘッドを回避できるためです。 Nullable<T> のメモリ フットプリントはどれくらいですか?. 。ただし、値が null であるかどうかを記憶する必要があるため、Null 非許容型よりも多くのメモリが必要になります。アライメントの問題と VM の実装に応じて、これは「完全な」オブジェクトより大幅に少なくなる場合もあれば、そうでない場合もあります。また、C#/CLR の値は具体化されるため、実行する必要があるリフティング操作を考慮してください。
// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true
記事 Java ヒント 130:データサイズを知っていますか? 参照型のメモリ消費 (Java の場合) について説明します。注意すべき点の 1 つは、JVM が内部的にプリミティブ型とオブジェクトごとに 1 つずつ、特殊なバージョンの配列を持っていることです (ただし、この記事には一部の配列が含まれていることに注意してください) 誤解を招く発言)。オブジェクト (vs.プリミティブ)は、余分なメモリ オーバーヘッドとバイト アラインメントの問題を引き起こします。ただし、C# では、最適化された配列のケースを拡張できます。 Nullable<T>
タイプとJVM が持つ特殊なケースは限られているため、 Nullable<T>
それ自体は単なる構造タイプ (または「プリミティブ」) です。
ただし、オブジェクトは、変数スロット内でオブジェクトへの「参照」を維持するために小さな固定サイズのみを必要とします。タイプの可変スロット Nullable<LargeStruct>
一方、スペースが必要です LargeStruct+Nullable
(スロット自体がヒープ上にある場合があります)。見る C# の概念:値と参照型. 。上記の「リフティング」の例では、変数の型がどのようになっているのかに注目してください。 object
: object
C# の「ルート型」 (参照型と値型の両方の親) であり、 ない 特殊な値タイプ。
1 C# 言語は、次の固定セットをサポートしています。 エイリアス 「フレンドリーな小文字」型名へのアクセスを許可するプリミティブ/共通型の場合。例えば、 double
のエイリアスです System.Double
そして int
のエイリアスです System.Int32
. 。別の場合を除き、 Double
型はスコープ内にインポートされます。 double
そして Double
C# では同じ型を参照します。特別な理由がない限り、エイリアスを使用することをお勧めします。
他のヒント
Nullable<double>
(別名 double?
) C# では ない と同じ Double
ジャワでは。
Java にオートボックス化/アンボックス化が導入される前は、プリミティブとファーストクラス オブジェクトの間で手動で変換する必要がありました。
Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();
Java 1.5 ではそれが変更されたため、次のようにするだけで済みます。
Double dblObj = 2.0;
double dblPrim = dblObj;
そして、Java は上記の例を自動的に反映するコードを挿入します。
C# は、「プリミティブ」型 (CLR で呼ばれるもの) が無制限に存在するため異なります。 値の型)。これらは主に Java のプリミティブと同様に動作します。 値のセマンティクス. 。新しい値の型を作成するには、 struct
キーワード。C# にはオートボックス化/アンボックス化があります 全て 値の型を定義し、すべての値の型を次から派生させます。 Object
.
したがって、値型を使用できます(次のように) double
) 任意のオブジェクト参照を使用します (例:のキーとして Dictionary
) 必要に応じてボックスに入れられます。そうでない場合は、そのまま使用されます。(C# のジェネリック実装は、ほとんどの状況でボックス化を回避するのに十分です。)
int
s、bool
s、などと「参照タイプ」 - - でC#、別のオブジェクトへの最善の方法は、プリミティブのようにちょっとある「値のタイプ」である。クラスなど