Konversi Lossy di Jawa

1. Ikhtisar

Dalam tutorial singkat ini, kita akan membahas konsep konversi lossy di Java dan alasan di baliknya.

Pada saat yang sama, kita akan mempelajari beberapa teknik konversi yang berguna untuk menghindari kesalahan ini.

2. Konversi Lossy

Konversi lossy hanyalah hilangnya informasi saat menangani data.

Di Java, ini sesuai dengan kemungkinan kehilangan nilai atau presisi variabel saat mengonversi satu jenis ke jenis lainnya.

Ketika kami mencoba untuk menetapkan variabel tipe berukuran besar ke tipe berukuran lebih kecil , Java akan menghasilkan kesalahan, tipe yang tidak kompatibel: kemungkinan konversi lossy , saat mengkompilasi kode.

Sebagai contoh, mari kita coba menetapkan long ke int :

long longNum = 10; int intNum = longNum;

Java akan mengeluarkan kesalahan saat menyusun kode ini:

incompatible types: possible lossy conversion from long to int

Di sini, Java akan menemukan ketidakcocokan panjang dan int dan mengakibatkan kesalahan konversi lossy. Karena bisa ada nilai panjang di luar kisaran int -2,147,483,648 hingga 2,147,483,647.

Demikian pula, mari kita coba menetapkan float ke long :

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

Karena float dapat memiliki nilai desimal yang tidak memiliki nilai panjang yang sesuai . Oleh karena itu, kami akan menerima kesalahan yang sama.

Demikian pula, menetapkan nomor ganda ke int akan menyebabkan kesalahan yang sama:

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

Nilai ganda bisa terlalu besar atau terlalu kecil untuk int dan nilai desimal akan hilang dalam konversi. Oleh karena itu, ini adalah konversi kerugian potensial.

Selain itu, kami dapat mengalami kesalahan ini saat melakukan penghitungan sederhana:

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

Saat perkalian ganda dengan int , kita mendapatkan hasilnya menjadi ganda . Akibatnya, ini juga merupakan konversi kerugian potensial.

Oleh karena itu, jenis yang tidak kompatibel dalam konversi lossy dapat memiliki ukuran atau jenis yang berbeda (bilangan bulat atau desimal).

3. Tipe Data Primitif

Di Java, ada banyak tipe data primitif yang tersedia dengan kelas pembungkusnya yang sesuai.

Selanjutnya, mari kita menyusun daftar praktis dari semua kemungkinan konversi lossy di Java:

  • pendek menjadi byte atau char
  • char menjadi byte atau short
  • int ke byte , short atau char
  • long to byte , short , char atau int
  • float ke byte , short , char , int atau long
  • double to byte , short , char , int , long atau float

Perhatikan bahwa meskipun pendek dan karakter memiliki ukuran yang sama. Namun, konversi dari short ke char bersifat lossy karena char adalah tipe data unsigned .

4. Teknik Konversi

4.1. Mengubah Jenis Primitif

Cara mudah untuk mengkonversi primitif untuk menghindari konversi lossy adalah melalui downcasting; dengan kata lain, mentransmisikan tipe berukuran lebih besar ke tipe berukuran lebih kecil. Oleh karena itu, ini juga disebut konversi primitif yang menyempit.

Misalnya, mari kita ubah angka panjang menjadi pendek menggunakan downcasting :

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

Demikian pula, mari kita ubah double menjadi int :

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

Namun, kita harus mencatat bahwa mengonversi tipe berukuran besar dengan nilai terlalu besar atau terlalu kecil ke tipe berukuran lebih kecil melalui downcasting dapat menghasilkan nilai yang tidak terduga.

Mari kita ubah nilai panjang di luar kisaran pendek :

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

Jika kami menganalisis konversi dengan cermat, kami akan melihat bahwa ini bukan nilai yang diharapkan.

Dengan kata lain, ketika Java mencapai nilai tertinggi dari tipe berukuran kecil saat mengonversi dari tipe berukuran besar, angka berikutnya adalah nilai terendah dari tipe berukuran kecil dan sebaliknya.

Mari kita pahami ini melalui contoh. Ketika largeLongNum dengan nilai 32768 diubah menjadi short , nilai shortNum1 adalah -32768 . Karena nilai maksimal short adalah 32767, oleh karena itu, Java berlaku untuk nilai min short berikutnya.

Demikian pula, saat smallLongNum diubah menjadi pendek . Nilai shortNum2 adalah 32767 karena Java berlaku untuk nilai maks berikutnya dari short .

Juga, mari kita lihat apa yang terjadi ketika kita mengonversi nilai maks dan min dari long menjadi 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. Mengonversi Antara Objek Pembungkus dan Jenis Primitif

To directly convert a wrapper object to a primitive, we can use various methods in wrapper classes such as intValue(), shortValue() and longValue(). This is called unboxing.

For instance, let's convert a Float object to a long:

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

Also, if we look at the implementation of longValue or similar methods, we'll find the use of narrowing primitive conversion:

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

However, at times, narrowing primitive conversion should be avoided to save valuable information:

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

After conversion, the value of longNum will be 15. However, the doubleNum is 15.9999, which is very close to 16.

Instead, we can use Math.round() for conversion to the closest integer:

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

4.3. Converting Between Wrapper Objects

For this, let's use the already discussed conversion techniques.

First, we'll convert wrapper object to a primitive value, downcast it and convert it to another wrapper object. In other words, we'll perform unboxing, downcasting, and boxing techniques.

For example, let's convert a Double object to an Integer object:

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

Lastly, we're using Integer.valueOf() to convert the primitive type int to an Integer object. This type of conversion is called boxing.

5. Conclusion

In this article, we've explored the concept of lossy conversion in Java with the help of a number of examples. In addition, we've compiled a handy list of all possible lossy conversions as well.

Along the way, we've identified narrowing primitive conversion as an easy technique to convert primitive numbers and avoid the lossy conversion error.

At the same time, we've also explored additional handy techniques for numeric conversions in Java.

The code implementations for this article can be found over on GitHub.