Penukaran Kerugian di Jawa

1. Gambaran keseluruhan

Dalam tutorial ringkas ini, kita akan membincangkan konsep penukaran kerugian di Java dan sebab di sebalik itu.

Pada masa yang sama, kami akan meneroka beberapa teknik penukaran yang berguna untuk mengelakkan ralat ini.

2. Penukaran Kerugian

Penukaran kerugian hanyalah kehilangan maklumat semasa mengendalikan data.

Di Jawa, ini sesuai dengan kemungkinan kehilangan nilai atau ketepatan pemboleh ubah sambil menukar satu jenis ke jenis lain.

Apabila kita berusaha menetapkan pemboleh ubah jenis bersaiz besar ke jenis berukuran lebih kecil , Java akan menghasilkan ralat, jenis yang tidak sesuai: kemungkinan penukaran kerugian , sambil menyusun kod.

Sebagai contoh, mari kita cuba memberikan panjang pada int :

long longNum = 10; int intNum = longNum;

Java akan mengeluarkan ralat semasa menyusun kod ini:

incompatible types: possible lossy conversion from long to int

Di sini, Java akan menemui panjang dan int yang tidak serasi dan mengakibatkan kesilapan penukaran. Kerana boleh ada nilai panjang di luar julat int -2,147,483,648 hingga 2,147,483,647.

Begitu juga, mari kita cuba untuk menetapkan apungan kepada panjang :

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

Sebagai pelampung boleh mempunyai nilai perpuluhan yang tidak mempunyai nilai panjang yang sepadan . Oleh itu, kami akan menerima ralat yang sama.

Begitu juga, memberikan nombor dua ke int akan menyebabkan ralat yang sama:

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

The double nilai boleh terlalu besar atau terlalu kecil untuk int dan perpuluhan nilainya akan hilang dalam penukaran. Oleh itu, ia adalah kemungkinan penukaran kerugian.

Kita juga boleh menghadapi ralat ini semasa melakukan pengiraan mudah:

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

Apabila gandaan berlipat ganda dengan int , kita mendapat hasilnya berganda . Oleh itu, ia juga merupakan penukaran kerugian yang berpotensi.

Oleh itu, jenis yang tidak serasi dalam penukaran lossy boleh mempunyai ukuran atau jenis yang berbeza (bilangan bulat atau perpuluhan).

3. Jenis Data Primitif

Di Jawa, terdapat banyak jenis data primitif yang tersedia dengan kelas pembungkus yang sesuai.

Seterusnya, mari kita susun senarai berguna dari semua kemungkinan penukaran kerugian di Java:

  • pendek ke bait atau char
  • char ke bait atau pendek
  • int to byte , pendek atau char
  • panjang hingga bait , pendek , char atau int
  • terapung ke bait , pendek , char , int atau panjang
  • dua hingga bait , pendek , char , int , panjang atau apungan

Perhatikan bahawa walaupun pendek dan char mempunyai ukuran yang sama. Namun, penukaran dari pendek ke arang adalah kerugian kerana char adalah jenis data yang tidak ditandatangani .

4. Teknik Penukaran

4.1. Menukar Antara Jenis Primitif

Cara mudah menukar primitif untuk mengelakkan penukaran yang hilang adalah melalui penyiaran; dengan kata lain, membuang jenis bersaiz lebih besar ke jenis bersaiz lebih kecil. Oleh itu, ia juga disebut penyempitan primitif penyempitan.

Sebagai contoh, mari kita menukar nombor panjang menjadi pendek menggunakan downcasting :

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

Begitu juga, mari kita menukar dua kali ganda menjadi int :

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

Namun, kita harus perhatikan bahawa menukar jenis bersaiz besar dengan nilai yang terlalu besar atau terlalu kecil menjadi jenis bersaiz lebih kecil melalui downcasting dapat menghasilkan nilai yang tidak dijangka.

Mari tukar nilai panjang di luar jangka pendek :

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

Sekiranya kita menganalisis penukaran dengan teliti, kita akan melihat bahawa ini bukan nilai yang diharapkan.

Dengan kata lain, ketika Java mencapai nilai tertinggi dari jenis bersaiz kecil sambil menukar dari jenis bersaiz besar, angka berikutnya adalah nilai terendah dari jenis bersaiz kecil dan sebaliknya.

Mari kita fahami ini melalui contoh. Apabila bigLongNum dengan nilai 32768 ditukar menjadi pendek , nilai shortNum1 adalah -32768 . Oleh kerana nilai maksimum pendek adalah 32767, oleh itu, Java mengambil nilai min pendek seterusnya.

Begitu juga ketika smallLongNum ditukar menjadi pendek . Nilai shortNum2 adalah 32767 kerana Java menggunakan nilai maksimum pendek .

Juga, mari kita lihat apa yang berlaku apabila kita menukar nilai maksimum dan min panjang 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. Menukar 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.