CodeGym /Java Blog /ランダム /プリミティブ型の拡大と縮小
John Squirrels
レベル 41
San Francisco

プリミティブ型の拡大と縮小

ランダム グループに公開済み
やあ!CodeGym を進めていくと、プリミティブ型に何度も遭遇することになります。これらについて私たちが知っていることの短いリストは次のとおりです。
  1. これらはオブジェクトではなく、メモリに格納されている値を表します。
  2. いくつかの種類があります
    • 整数: byteshortintlong
    • 浮動小数点 (小数) 数値: floatおよびdouble
    • 論理値:ブール値
    • 記号値 (文字と数字を表すため): char
  3. 各タイプには独自の値の範囲があります。

プリミティブ型 メモリ内のサイズ 値の範囲
バイト 8ビット -128~127
短い 16ビット -32768 ~ 32767
文字 16ビット 0~65536
整数 32ビット -2147483648 ~ 2147483647
長さ 64ビット -9223372036854775808 ~ 9223372036854775807
浮く 32ビット (2 の -149 乗) から ((2 - (2 の -23 乗)) * 2 の 127 乗)
ダブル 64ビット (-2 の 63 乗) から ((2 の 63 乗) - 1)
ブール値 8 (配列で使用される場合)、32 (配列で使用されない場合) 正しいか間違っているか
ただし、値が異なるだけでなく、メモリ内で占有する領域も異なります。int1 バイト以上のデータを必要とします。そして、ロングはショートよりも大きいです。プリミティブによって占有されるメモリの量は、ロシアの入れ子人形と比較できます。 プリミティブ型の拡大と縮小 - 2 各入れ子人形の内部には利用可能なスペースがあります。入れ子人形が大きいほど、より多くのスペースがあります。大きな入れ子人形 (長い) は、小さなint を簡単に収容できます。簡単にフィットするので、他に何もする必要はありません。Java では、プリミティブを操作するとき、これを暗黙的な変換と呼びます。別の言い方をすると、ワイドニングと呼ばれます。

Javaでの拡大

ワイドニング変換の簡単な例を次に示します。

public class Main {

   public static void main(String[] args) {
      
       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
ここでは、バイト値をint変数に代入します。割り当ては問題なく成功します。バイトに格納された値は、int が収容できるメモリよりも少ないメモリを消費します。小さな入れ子人形 (バイト値) は、大きな入れ子人形 ( int変数) の中に簡単に収まります。逆のこと、つまり、そのような大きなデータ型を収容できない範囲の変数に大きな値を入れようとする場合は、別の問題になります。本物の入れ子人形では、その数はまったく収まりません。Java ではそれが可能ですが、微妙な違いがあります。int をshort変数に入れてみましょう。

public static void main(String[] args) {

   int bigNumber = 10000000;
  
   short littleNumber = 1000;

   littleNumber = bigNumber;// Error!
   System.out.println(bigNumber);
}
エラー!コンパイラーは、大きなネスト人形 ( int ) を小さな人形 ( short ) の中に押し込むことで、何か異常なことをしようとしていると理解します。この場合、コンパイル エラーはコンパイラからの警告です。「これを実行することに本当に確信がありますか?」確信がある場合は、コンパイラーに「すべて問題ありません。何をしているのかわかっています!」と伝えます。 このプロセスは、明示的な型変換、または縮小と呼ばれます。

Java での絞り込み

縮小変換を実行するには、値の変換先の型を明示的に指定する必要があります。言い換えれば、コンパイラーの質問に答える必要があります。「それで、この大きな入れ子人形を、これらの小さな入れ子人形のどれに入れますか?」 私たちの場合、次のようになります。

public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
int をshort変数に 入れたいことと、責任を負うことを明示的に示します。コンパイラは、より狭い型が明示的に指定されていることを確認して、変換を実行します。結果はどうなりましたか? コンソール出力: -27008 これは少し予想外でした。正確にはなぜそれがわかったのでしょうか? 実際、それはすべて非常に簡単です。元々の値は 10000000 で、 32 ビットを占有するint変数に格納されていました。これはそのバイナリ表現です。
プリミティブ型の拡大と縮小 - 3
この値をshort変数 に書き込みます。この変数には 16 ビットしか格納できません。したがって、数値の最初の 16 ビットのみがそこに移動されます。残りは破棄されます。その結果、short 変数は次の値を受け取ります。
プリミティブ型の拡大と縮小 - 4
10 進数形式では -27008 に等しいため、コンパイラは、特定の型への明示的な縮小変換を示すことで「確認」するよう求めます。まず、これはあなたが結果に対して責任を負っていることを示しています。次に、変換時にどのくらいのスペースを割り当てるかをコンパイラーに指示します。結局のところ、最後の例で、 short ではなく int 値を byte 変数に割り当てた場合自由に使えるのは 16 ビットではなく 8 ビットだけになり、結果は異なります。小数型 ( floatおよびdouble ) には、変換を絞り込むための独自のプロセスがあります。小数部の数値を整数型にキャストしようとすると、小数部は破棄されます。

public static void main(String[] args) {

   double d = 2.7;

   long x = (int) d;
   System.out.println(x);
}
コンソール出力: 2

文字

charは個々の文字を表示するために使用されることはすでにご存知でしょう。

public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';
  
}
ただし、このデータ型には、理解することが重要ないくつかの特徴があります。値の範囲の表をもう一度見てみましょう。
プリミティブ型 メモリ内のサイズ 値の範囲
バイト 8ビット -128~127
短い 16ビット -32768 ~ 32767
文字 16ビット 0~65536
整数 32ビット -2147483648 ~ 2147483647
長さ 64ビット -9223372036854775808 ~ 9223372036854775807
浮く 32ビット (2 の -149 乗) から ((2 - (2 の -23 乗)) * 2 の 127 乗)
ダブル 64ビット (-2 の 63 乗) から ((2 の 63 乗) - 1)
ブール値 8 (配列で使用される場合)、32 (配列で使用されない場合) 正しいか間違っているか
char型 の場合は0~65536の範囲を示します。しかし、それは何を意味するのでしょうか?結局のところ、char は数字だけでなく、文字や句読点も表します。Java ではchar値は Unicode 形式で格納されます。Unicode については、前のレッスンですでに説明しました。おそらく、Unicode は、世界中のほぼすべての書き言葉の記号を含む文字エンコード標準であることを覚えているでしょう。言い換えれば、これはあらゆる言語のほぼすべての文字を表す特別なコードのリストです。Unicode テーブル全体は非常に大きいので、もちろん、暗記する必要はありません。そのほんの一部を次に示します。 プリミティブ型の拡大と縮小 - 5 重要なことは、文字がどのように格納されるかを理解し、特定の文字のコードを知っていれば、プログラム内でいつでもその文字を生成できることを覚えておくことです。乱数を使って試してみましょう:

public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
コンソール出力: 耰 これは、 Java でcharを 格納するために使用される形式です。各シンボルは数値、つまり 16 ビット (2 バイト) の数値コードに対応します。Unicode では、32816 は漢字「耰」に対応します。 次の点に注意してください。この例では、int変数を使用しました。これはメモリ内で 32 ビットを占有しますが、charは16 ビットを占有します。数値 (32816) はshortに収まらないため、ここではintを選択しました。char ( shortと同様)のサイズは 16 ビットですが、 charの範囲には負の数はないため、 charの「正」の部分は範囲は 2 倍になります (ショートタイプの場合は 32767 ではなく 65536 )。コードが 65536 未満である限り、int を使用できます。ただし、65536 を超えるint値を作成すると、16 ビット以上を占有することになります。これにより、コンバージョンが絞り込まれます

char c = (char) x;
余分なビットは破棄され (上で説明したように)、結果はまったく予期しないものになります。

文字と整数を追加する特別な機能

珍しい例を見てみましょう。

public class Main {

   public static void main(String[] args) {

      char c = '1';

      int i = 1;

       System.out.println(i + c);
   }
}
コンソール出力: 50 O_О それはどういう意味ですか? 1+1。50はどこから来たのですか?char値は 0 ~ 65536 の範囲の数値としてメモリに格納され、これらの数値は文字の Unicode 表現であることはすでに ご存知でしょう。charと整数型をプリミティブ型の拡大と縮小 - 6 追加すると、 char は対応する Unicode 数値に変換されます。私たちのコードでは、1 と '1' を加算すると、シンボル '1' が独自のコードである 49 に変換されました (これは上の表で確認できます)。したがって、結果は 50 になります。もう一度、旧友の耰を例として、これを何らかの数値に足してみましょう。

public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
コンソール出力: 33016 耰が 32816 に対応することはすでに発見しています。そして、この数値と 200 を加算すると、結果は 33016 になります。:) ご覧のとおり、ここでのアルゴリズムは非常に単純ですが、忘れてはなりません。 。

さらに読む:

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION