1. タイプキャスト

Java での型キャスト

プリミティブ型の変数 (型を除くboolean) は、さまざまな型の数値を格納するために使用されます。変数の型は変更されませんが、ある型から別の型に変換できる場所があります。そしてその場所は割り当てです。

異なる型の変数を相互に割り当てることができます。これを行うと、ある型の変数の値が別の型の値に変換され、2 番目の変数に割り当てられます。この点に関して、拡張と縮小という 2 種類の型変換を識別できます。

拡大は、値を小さなバスケットから大きなバスケットに移動することに似ています。この操作はシームレスで痛みがありません。絞り込みは、値を大きなバスケットから小さなバスケットに移動するときに発生します。十分なスペースがない可能性があり、何かを破棄する必要があります。

バスケットのサイズ別に分類したタイプは次のとおりです。

Java 2 での型キャスト


2. 型変換の拡張

多くの場合、ある数値型の変数を別の数値型の変数に割り当てることが必要になります。どうやってそれを行うのですか?

Java には 4 つの整数型があります。

タイプ サイズ
byte 1 byte
short 2 bytes
int 4 bytes
long 8 bytes

小さいバスケットに格納されている変数は、いつでも大きいバスケットに格納されている変数に割り当てることができます。

int、変数への代入shortbyte簡単に行えますlongshort変数を変数byteに代入することもできますint。また、byte変数には変数を割り当てることができますshort

例:

コード 説明
byte a = 5;
short b = a;
int c = a + b;
long d = c * c;
このコードは問題なくコンパイルされます。

このような、小さい型から大きい型への変換は、拡張型変換と呼ばれます。

実数についてはどうでしょうか?

彼らにとってはすべてが同じであり、サイズが重要です。

タイプ サイズ
float 4 bytes
double 8 bytes

floatdouble変数には問題なく代入できます。しかし、整数型ではさらに興味深いことが起こります。

任意の整数変数をfloat変数に割り当てることができます。型もlong8 バイト長です。そして、任意の整数変数またはfloat変数をdouble変数に割り当てることができます。

コード ノート
long a = 1234567890;
float b = a;
double c = a;

b == 1.23456794E9
c == 1.23456789E9

実数型に変換すると、十分な有効桁数が不足するため精度が失われる可能性があることに注意してください。

整数から浮動小数点数に変換する場合、数値の下位部分が切り捨てられることがあります。ただし、小数は近似値を格納すると理解されているため、そのような代入演算は許可されます。


3. 型の縮小変換

他の可能性についてはどうでしょうか? long変数に値を代入する必要がある場合はどうすればよいでしょうかint?

変数をバスケットとして想像してください。1、2、4、8 バイトなど、さまざまなサイズのバスケットをご用意しています。リンゴを小さなカゴから大きなカゴに移すのは問題ありません。しかし、大きなかごから小さなかごに移すと、リンゴの一部が失われる可能性があります。

より大きな型からより小さな型へのこの変換は、縮小型変換と呼ばれます。このような代入操作を実行する場合、数値の一部が新しい変数に適合しないため、破棄される可能性があります。

型を絞り込むときは、間違いではないこと、数値の一部を意図的に破棄していることをコンパイラに明示的に伝える必要があります。これには、型キャスト演算子が使用されます。括弧内は型名です。

このような状況では、Java コンパイラはプログラマにタイプキャスト演算子を指定することを要求します。一般に、次のようになります。

(type) expression

例:

コード 説明
long a = 1;
int b = (int) a;
short c = (short) b;
byte d = (byte) c;
毎回、型キャスト演算子を明示的に指定する必要があります

ここでaは に等しいので1、型キャスト演算子は過剰に思えるかもしれません。しかし、aもっと大きかったらどうでしょうか?

コード 説明
long a = 1000000;
int b = (int) a;
short c = (short) b;
byte d = (byte) c;
a == 1000000
b == 1000000
c == 16960
d == 64

100 万はlongと に完全に収まりますint。ただし、変数に 100 万を割り当てる場合short、最初の 2 バイトは破棄され、最後の 2 バイトのみが保持されます。そして、 に代入するとbyte、残るのは最後のバイトだけです。

メモリ内での数値の配置方法:

タイプ 2進数表記 10進数表記
int 0b 00000000 00001111 01000010 01000000 1000000
short 0b 01000010 01000000 16.960
byte 0b 01000000 64

charタイプ

a はchar、 a と同様にshort2 バイトを占有しますが、一方を別のものに変換するには、常に型キャスト演算子を使用する必要があります。ここでの問題は、型が符号付きで~ のshort値を含めることができるのに対し、型は符号なしで~ の値を含めることができることです。-32,768+32,767char065,535

負の数は に格納できませんcharが、 に格納することはできますshort。また、 にはshortより大きい数値を格納できません32,767が、そのような数値は に格納できますchar


4. 式の種類

異なる型の変数が同じ式で使用されている場合はどうなるでしょうか? 論理的には、最初に共通の型に変換する必要があることがわかります。しかし、どれでしょうか?

もちろん、より大きなものに。

Java は常に、より大きな型に変換します。大まかに言うと、まず型の 1 つが拡張され、その後初めて同じ型の値を使用して操作が実行されます。

anintと a がlong式に含まれている場合、 の値はinta に変換されてlongからのみ操作が続行されます。

コード 説明
int a = 1;
long b = 2;
long c = a + b;
aは a に拡張されlong、加算が行われます。

浮動小数点数

式に整数と浮動小数点数 (floatまたは) が含まれる場合、整数は浮動小数点数 (または) に変換され、その後でのみ演算が実行されます。doublefloatdouble

操作に afloatと a が含まれる場合double、 はfloatに変換されますdouble。これは実際に期待されています。

サプライズ

byteshortおよび型は、相互に対話するときにchar常に に変換されます。intこの型が標準の整数型とみなされるのには十分な理由がありますint

byteaと a を乗算するとshort、 が得られますintbyteaと a を乗算するとbyte、 が得られますintbyteaと a を追加してもbyte、 が得られますint

これにはいくつかの理由があります。例:

コード 説明
byte a = 110;
byte b = 120;
byte c = a * b;  // Error
110 * 120これは13,200、次の型の最大値よりわずかに大きい値ですbyte127
byte a = 110;
byte b = 120;
byte c = a + b; // Error
110 + 120は であり230、これも次の型の最大値よりわずかに大きくなりますbyte127

一般に、8 ビット (1 バイト) の数値と 8 ビット (1 バイト) の数値を乗算すると、16 ビット (2 バイト) を占める数値が得られます。

その結果、 より小さい整数型のすべての演算は、int常に直ちにints に変換されます。つまり、 より小さい型の変数に計算結果を格納したい場合は、int常に型キャスト演算子を明示的に指定する必要があります。

例:

コード 説明
byte a = 110;
byte b = 120;
byte c = (byte) (a * b);
byte * byteは次のようになります。int
byte a = 110;
byte b = 120;
byte c = (byte) (a + b);
byte + byteは次のようになります。int
byte a = 1;
byte b = (byte) (a + 1);
byte + intは になります。int
リテラルのものは ですint

5. 重要なニュアンス

型キャスト演算子はかなり高い優先順位を持っています。

つまり、式にたとえば加算とタイプキャスト演算子が含まれる場合、加算の前にタイプキャストが実行されます。

例:

コード 説明
byte a = 1;
byte b = 2;
byte c = (byte) a * b;
タイプキャスト演算子はa、すでに である変数にのみ適用されますbyte。このコードはコンパイルされません。
byte a = 1;
byte b = 2;
byte c = (byte) (a * b);
これが正しい方法です。

式の 1 つのコンポーネントだけではなく、式全体を特定の型に変換する場合は、式全体をかっこで囲み、前にタイプキャスト演算子を置きます。