1. 概要

このクイックチュートリアルでは、Javaでの不可逆変換の概念とその背後にある理由について説明します。

同時に、このエラーを回避するためのいくつかの便利な変換手法についても説明します。

2. 非可逆変換

非可逆変換とは、データの処理中に情報が失われることです。

Javaでは、あるタイプを別のタイプに変換するときに変数の値または精度が失われる可能性に対応します。

大きいサイズのタイプの変数を小さいサイズのタイプに割り当てようとすると、Javaはエラー、互換性のないタイプ:コードのコンパイル中に損失のある変換の可能性、を生成します。

たとえば、longintに割り当ててみましょう。

long longNum = 10;
int intNum = longNum;

このコードのコンパイル中にJavaはエラーを出します:

incompatible types: possible lossy conversion from long to int

ここで、Javaはlongintに互換性がないことを検出し、不可逆変換エラーを引き起こします。 intの範囲-2,147,483,648から2,147,483,647の範囲外のlong値が存在する可能性があるためです。

同様に、floatlongに割り当ててみましょう。

float floatNum = 10.12f;
long longNum = floatNum;
incompatible types: possible lossy conversion from float to long

float は、対応するlong値を持たない10進値を持つ可能性があるため。 したがって、同じエラーが発生します。

同様に、double番号をintに割り当てると、同じエラーが発生します。

double doubleNum = 1.2;
int intNum = doubleNum;
incompatible types: possible lossy conversion from double to int

double の値は、 int に対して大きすぎるか小さすぎる可能性があり、変換中に10進値が失われます。 したがって、それは潜在的な損失のある変換です。

また、簡単な計算を実行しているときにこのエラーが発生する可能性があります。

int fahrenheit = 100;
int celcius = (fahrenheit - 32) * 5.0 / 9.0;

doubleintを掛けると、doubleの結果が得られます。 その結果、それは潜在的な損失のある変換でもあります。

したがって、非可逆変換の互換性のないタイプは、サイズまたはタイプ(整数または小数)が異なる可能性があります。

3. プリミティブデータ型

Javaには、対応するラッパークラスで使用できる多くのプリミティブデータ型があります。

次に、Javaで発生する可能性のあるすべての不可逆変換の便利なリストをまとめましょう。

  • shortからbyteまたはchar
  • charからbyteまたはshort
  • intからbyteshortまたはchar
  • longからbyte short char 、または int
  • floatからbyte short char int 、または long
  • doubleからbyte short char int long 、または[X96X ] float

shortcharのサイズは同じですが注意してください。 それでも、charは符号なしデータ型であるため、shortからcharへの変換は不可逆です。

4. 変換テクニック

4.1. プリミティブタイプ間の変換

プリミティブを変換して損失のある変換を回避する簡単な方法は、ダウンキャストを使用することです。 つまり、大きいサイズのタイプを小さいサイズのタイプにキャストします。 したがって、ナローイングプリミティブ変換とも呼ばれます。

たとえば、ダウンキャスティングを使用して、長い数値を短いに変換してみましょう。

long longNum = 24;
short shortNum = (short) longNum;
assertEquals(24, shortNum);

同様に、doubleintに変換してみましょう。

double doubleNum = 15.6;
int integerNum = (int) doubleNum;
assertEquals(15, integerNum);

ただし、値が大きすぎる、または小さすぎる大きいサイズの型をダウンキャストによって小さいサイズの型に変換すると、予期しない値になる可能性があることに注意してください。

shortの範囲外のlong値を変換してみましょう。

long largeLongNum = 32768; 
short minShortNum = (short) largeLongNum;
assertEquals(-32768, minShortNum);

long smallLongNum = -32769;
short maxShortNum = (short) smallLongNum;
assertEquals(32767, maxShortNum);

変換を注意深く分析すると、これらは期待値ではないことがわかります。

つまり、Javaが大きいサイズのタイプから変換中に小さいサイズのタイプの最大値に達すると、次の数値は小さいサイズのタイプの最小値になり、その逆も同様です。

例を通してこれを理解しましょう。 32768の値を持つlargeLongNumshortに変換すると、shortNum1の値は-32768になります。 X160X] short は32767であるため、Javaはshortの次の最小値を取得します。

同様に、smallLongNumshortに変換される場合。 shortNum2 の値は32767です。これは、Javaがshortの次の最大値を取得するためです。

また、longの最大値と最小値をintに変換するとどうなるか見てみましょう。

long maxLong = Long.MAX_VALUE; 
int minInt = (int) maxLong;
assertEquals(-1, minInt);

long minLong = Long.MIN_VALUE;
int maxInt = (int) minLong;
assertEquals(0, maxInt);

4.2. ラッパーオブジェクトとプリミティブタイプ間の変換

ラッパーオブジェクトをプリミティブに直接変換するには、 intValue() shortValue() longValue()などのラッパークラスのさまざまなメソッドを使用できます。 これはunboxingと呼ばれます。

たとえば、Floatオブジェクトをlongに変換してみましょう。

Float floatNum = 17.564f;
long longNum = floatNum.longValue();
assertEquals(17, longNum);

また、 longValue または同様のメソッドの実装を見ると、ナローイングプリミティブ変換の使用がわかります。

public long longValue() {
    return (long) value;
}

ただし、貴重な情報を保存するために、プリミティブ変換を絞り込むことは避けてください。

Double doubleNum = 15.9999;
long longNum = doubleNum.longValue();
assertEquals(15, longNum);

変換後、longNumの値は15になります。 ただし、 doubleNum は15.9999であり、16に非常に近い値です。

代わりに、 Math.round()を使用して最も近い整数に変換できます。

Double doubleNum = 15.9999;
long longNum = Math.round(doubleNum);

assertEquals(16, longNum);

4.3. ラッパーオブジェクト間の変換

このために、すでに説明した変換手法を使用しましょう。

まず、ラッパーオブジェクトをプリミティブ値に変換し、ダウンキャストして、別のラッパーオブジェクトに変換します。 つまり、開封、ダウンキャスト、ボクシングのテクニックを実行します。

たとえば、DoubleオブジェクトをIntegerオブジェクトに変換してみましょう。

Double doubleNum = 10.3;
double dbl = doubleNum.doubleValue(); // unboxing
int intgr = (int) dbl; // downcasting
Integer intNum = Integer.valueOf(intgr);
assertEquals(Integer.valueOf(10), intNum);

最後に、 IntegervalueOf()を使用して、プリミティブ型intIntegerオブジェクトに変換しています。 このタイプの変換は、ボクシングと呼ばれます。

5. 結論

この記事では、いくつかの例を使用して、Javaでの不可逆変換の概念について説明しました。 さらに、損失の可能性のあるすべての変換の便利なリストもまとめました。

その過程で、プリミティブ数を変換し、不可逆変換エラーを回避するための簡単な手法として、プリミティブ変換のナローイングを特定しました。

同時に、Javaでの数値変換のための追加の便利なテクニックも検討しました。

この記事のコード実装は、GitHubにあります。