1. 序章

Javaは型付き言語であり、型の概念を利用していることを意味します。 2つの異なるタイプグループがあります。

  1. プリミティブデータ型
  2. 抽象データ型。

この記事では、プリミティブ型の変換に焦点を当てます。

2. プリミティブの概要

最初に知っておく必要があるのは、プリミティブ型で使用できる値の種類です。 次の8つのプリミティブタイプがあります。

  • byte –8ビットおよび符号付き

  • short –16ビットおよび符号付き

  • char –16ビットおよび符号なし。Unicode文字を表すことができます。

  • int –32ビットおよび符号付き

  • long –64ビットおよび符号付き

  • float –32ビットおよび符号付き

  • double –64ビットおよび符号付き

  • boolean –数値ではなく、trueまたはfalseの値のみを持つことができます

これは、プリミティブについての広範な議論を目的としたものではなく、変換中に必要に応じて、プリミティブについてもう少し詳しく説明します。

3. プリミティブ変換の拡大

宛先タイプよりも単純または小さいプリミティブから変換する必要がある場合、そのために特別な表記を使用する必要はありません。

int myInt = 127;
long myLong = myInt;

拡大変換中、小さいプリミティブ値は大きいコンテナの上に配置されます。これは、値の左側にあるすべての余分なスペースがゼロで埋められることを意味します。 これは、整数グループから浮動小数点に移動するためにも使用できます。

float myFloat = myLong;
double myDouble = myLong;

これが可能なのは、より広いプリミティブに移動しても情報が失われないためです。

4. プリミティブ変換の絞り込み

変数宣言で使用される型よりも大きい値を適合させる必要がある場合があります。 一部のバイトを破棄する必要があるため、これにより情報が失われる可能性があります。

この場合、キャストを使用して、状況を認識していることを明示的に表現する必要があり、それに同意します。

int myInt = (int) myDouble;
byte myByte = (byte) myInt;

5. プリミティブ変換の拡大と縮小

この状況は、バイトからcharに変換する非常に特殊なケースで発生します。 最初の変換は、バイトから int への拡張であり、次にintからcharへの拡張です。

例でこの点を明確にします。

byte myLargeValueByte = (byte) 130;   //0b10000010 -126

130のバイナリ表現は-126でも同じですが、違いは信号ビットの解釈です。 byteからcharに変換してみましょう。

char myLargeValueChar = (char) myLargeValueByte;
  //0b11111111 10000010 unsigned value
int myLargeValueInt = myLargeValueChar; //0b11111111 10000010 65410

char 表現はUnicode値ですが、 int に変換すると、下位8ビットが-126とまったく同じである非常に大きな値が示されました。

再度byteに変換すると、次のようになります。

byte myOtherByte = (byte) myLargeValueInt; //0b10000010 -126

使用した元の値。 コード全体がcharで始まっている場合、値は異なります。

char myLargeValueChar2 = 130; //This is an int not a byte! 
  //0b 00000000 10000010 unsigned value
        
int myLargeValueInt2 = myLargeValueChar2; //0b00000000 10000010  130
        
byte myOtherByte2 = (byte) myLargeValueInt2; //0b10000010 -126

byte 表現は同じである-126ですが、char表現は2つの異なる文字を提供します。

6. ボクシング/開開変換

Javaでは、プリミティブ型ごとにラッパークラスがあります。これは、すべてをヘビーウェイトオブジェクト参照として持つオーバーヘッドなしに、プログラマーに便利な処理メソッドを提供する賢い方法です。 Java 1.5以降、プリミティブとオブジェクトを自動的に変換したり、オブジェクトに変換したり、元に戻したりする機能が含まれ、単純なアトリビューションによって実現されました。

Integer myIntegerReference = myInt;
int myOtherInt = myIntegerReference;

7. 文字列変換

すべてのプリミティブ型は、ラッパークラスを介して String に変換できます。これは、 toString()メソッドをオーバーライドします。

String myString = myIntegerReference.toString();

プリミティブ型に戻る必要がある場合は、対応するラッパークラスによって定義された解析メソッドを使用する必要があります。

byte  myNewByte   = Byte.parseByte(myString);
short myNewShort  = Short.parseShort(myString);
int   myNewInt    = Integer.parseInt(myString);
long  myNewLong   = Long.parseLong(myString);

float  myNewFloat  = Float.parseFloat(myString);
double myNewDouble = Double.parseDouble(myString);
boolean myNewBoolean = Boolean.parseBoolean(myString);

ここでの唯一の例外はCharacterクラスです。これは、Stringcharで構成されているためです。このように、おそらく String 単一のcharで構成されている場合、 StringクラスのcharAt()メソッドを使用できます。

char myNewChar = myString.charAt(0);

8. 数値プロモーション

二項演算を実行するには、両方のオペランドのサイズに互換性がある必要があります。

適用される一連の簡単なルールがあります。

  1. オペランドの1つがdoubleの場合、もう1つはdoubleにプロモートされます。
  2. それ以外の場合、オペランドの1つが float の場合、もう1つはfloatにプロモートされます。
  3. それ以外の場合、オペランドの1つが long の場合、もう1つはlongにプロモートされます。
  4. それ以外の場合は、両方ともintと見なされます

例を見てみましょう:

byte op1 = 4;
byte op2 = 5;
byte myResultingByte = (byte) (op1 + op2);

両方のオペランドがintにプロモートされ、結果をbyteに再度ダウンキャストする必要があります。

9. 結論

タイプ間の変換は、日常のプログラミング活動で非常に一般的なタスクです。 静的に型付けされた言語がそれらの変換を操作する方法を管理する一連のルールがあります。このルールを知っていると、特定のコードがコンパイルされているかどうかを理解しようとするときに多くの時間を節約できます。

この記事で使用されているコードは、GitHubにあります。