Error incompatible types possible lossy conversion from double to float

I've been running this code and keep receiving errors, not sure why. Double to float? Keep receiving message "error: incompatible types: possible lossy conversion from double to float ." Is

I’ve been running this code and keep receiving errors, not sure why. Double to float?
Keep receiving message «error: incompatible types: possible lossy conversion from double to float .» Is there any issue with conversions how to the conversion so there is no error
This is part of a larger code.

  public static float getAreaOfPentagon(float l) {
  float area = Math.sqrt(5 * (5 + 2 * (Math.sqrt(5))) * l * l) / 4;
  return area;
}

asked Sep 28, 2020 at 3:31

tiya's user avatar

1

You need to cast. Or declare area as double.

float area = (float)(Math.sqrt(5 * (5 + 2 *
   (Math.sqrt(5))) * l * l) / 4);

or

double area = Math.sqrt(5 * (5 + 2 *
   (Math.sqrt(5))) * l * l) / 4;

Aside: you are mixing integers and floating point in the same equation. Often this leads to disaster. It’s probably better to use double literals.

double area = Math.sqrt(5.0 * (5.0 + 2.0 *
   (Math.sqrt(5.0))) * l * l) / 4.0;

answered Sep 28, 2020 at 3:33

markspace's user avatar

markspacemarkspace

10.4k3 gold badges23 silver badges39 bronze badges

1. Overview

In this quick tutorial, we’ll discuss the concept of lossy conversion in Java and the reason behind it.

At the same time, we’ll explore some handy conversion techniques to avoid this error.

Lossy conversion is simply the loss of information while handling data.

In Java, it corresponds to the possibility of losing the value or precision of a variable while converting one type to another.

When we try to assign a variable of large-sized type to a smaller sized type, Java will generate an error, incompatible types: possible lossy conversion, while compiling the code.

For example, let’s try to assign a long to an int:

long longNum = 10;
int intNum = longNum;

Java will emit an error while compiling this code:

incompatible types: possible lossy conversion from long to int

Here, Java will find long and int incompatible and result in lossy conversion error. Because there can be long values outside the int range -2,147,483,648 to 2,147,483,647.

Similarly, let’s try to assign a float to a long:

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

As float can have decimal values that don’t have corresponding long value. Therefore, we’ll receive the same error.

Similarly, assigning a double number to an int will cause the same error:

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

The double values can be too large or too small for an int and decimal values will get lost in the conversion. Hence, it is a potential lossy conversion.

Also, we can run into this error while performing a simple calculation:

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

When a double multiply with an int, we get the result in a double. Consequently, it is also a potential lossy conversion.

Therefore, the incompatible types in lossy conversion can either have different sizes or types (integers or decimals).

3. Primitive Data Types

In Java, there are many primitive data types available with their corresponding wrapper classes.

Next, let’s compile a handy list of all possible lossy conversions in Java:

  • short to byte or char
  • char to byte or short
  • int to byte, short or char
  • long to byte, short, char or int
  • float to byte, short, char, int or long
  • double to byte, short, char, int, long or float

Note that though short and char have the same size. Still, the conversion from short to char is lossy because char is an unsigned data type.

4. Conversion Techniques

4.1. Converting Between Primitive Types

The easy way of converting primitives to avoid lossy conversion is through downcasting; in other words, casting the larger-sized type to a smaller-sized type. Hence, it is also called narrowing primitive conversion.

For instance, let’s convert a long number to a short using downcasting:

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

Similarly, let’s convert a double to an int:

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

However, we should note that converting large-sized type with values too large or too small to smaller-sized type through downcasting can result in unexpected values.

Let’s convert long values outside the range of short:

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

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

If we carefully analyze the conversion, we’ll see that these are not the expected values.

In other words, when Java hits the highest value of a small-sized type while converting from large-sized type, the next number is the lowest value of the small-sized type and vice-versa.

Let’s understand this through examples. When largeLongNum with the value of 32768 is converted to short, the value of shortNum1 is -32768. Because the max value of short is 32767, therefore, Java goes for the next min value of the short.

Similarly, when smallLongNum is converted to short. The value of shortNum2 is 32767 as Java goes for the next max value of the short.

Also, let’s see what happens when we convert the max and min values of a long to an 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. Converting Between Wrapper Objects and Primitive Types

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.

Содержание

  1. Java: incompatible types, possible lossy conversion from double to float [duplicate]
  2. 2 Answers 2
  3. Linked
  4. Related
  5. Hot Network Questions
  6. What does «possible lossy conversion» mean and how do I fix it?
  7. 1 Answer 1
  8. What does «potentially lossy» mean?
  9. How do you fix the error?
  10. «Possible lossy conversion» when subscripting.
  11. «Possible lossy conversion» in method or constructor calls
  12. «Possible lossy conversion» in a return statement.
  13. «Possible lossy conversion» due to promotion in expressions
  14. «Possible lossy conversion» when assigning literals
  15. Possible lossy conversion from double to float, given float values? [duplicate]
  16. 4 Answers 4
  17. getting error: incompatible types: possible lossy conversion from double to float for type promotion code
  18. 2 Answers 2
  19. Linked
  20. Related
  21. Hot Network Questions
  22. Subscribe to RSS
  23. How to Handle the Incompatible Types Error in Java
  24. Introduction to Data Types & Type Conversion
  25. Incompatible Types Error: What, Why & How?
  26. Incompatible Types Error Examples
  27. Explicit type casting

Java: incompatible types, possible lossy conversion from double to float [duplicate]

why do I get this error message when i try to compile the following code?

incompatible types: possible lossy conversion from double to float

Am i getting an overflow? I’m looking to understand the theory behind this. Thanks in advance.

2 Answers 2

Use float literals:

0.1 and 0.002 are double literals. Java’s double type has more precision than its float type. So, when you convert from double to float , the number may be changed by rounding it to the nearest value representable in float . Using decimal as an analogy, assigning the four-digit .1234 to a two-digit type would produce a different number, .12.

When you do this conversion implicitly, by assignment to a float variable, the compiler tells you there could be a loss of information. By using a cast, you tell the compiler the conversion to a less precise format is intentional. Or by using float literals such as 0.1f and 0.002f , you work with float values throughout and avoid conversion.

Generally, pick one type, float or double and use it throughout your calculations, for both literals and variables.

Linked

Hot Network Questions

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.1.14.43159

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

What does «possible lossy conversion» mean and how do I fix it?

New Java programmers are often confused by compilation error messages like:

«incompatible types: possible lossy conversion from double to int»

for this line of code:

In general, what does the «possible lossy conversion» error message mean, and how do you fix it?

1 Answer 1

First of all, this is a compilation error. If you ever see it in an exception message at runtime, it is because you have have run a program with compilation errors 1 .

The general form of the message is this:

«incompatible types: possible lossy conversion from to «

where and are both primitive numeric types; i.e. one of byte , char , short , int , long , float or double .

This error happens when your code attempts to do an implicit conversion from to but the conversion could be lossy.

In the example in the question:

the sqrt method produces a double , but a conversion from double to int is potentially lossy.

What does «potentially lossy» mean?

Well lets look at a couple of examples.

A conversion of a long to an int is a potentially lossy conversion because there are long values that do not have a corresponding int value. For example, any long value that is greater than 2^31 — 1 is too large to be represented as an int . Similarly, any number less than -2^31 is too small.

A conversion of an int to a long is NOT lossy conversion because every int value has a corresponding long value.

A conversion of a float to an long is a potentially lossy conversion because there float values that are outside of the range that can be represented as long values. Such numbers are (lossily) convert into Long.MAX_VALUE or Long.MIN_VALUE , as are NaN and Inf values.

A conversion of an long to a float is NOT lossy conversion because every long value has a corresponding float value. (The converted value may be less precise, but «lossiness» doesn’t mean that . in this context.)

These are all the conversions that are potentially lossy:

  • short to byte or char
  • char to byte or short
  • int to byte , short or char
  • long to byte , short , char or int
  • float to byte , short , char , int or long
  • double to byte , short , char , int , long or float .

How do you fix the error?

The way to make the compilation error go away is to add a typecast. For example;

But is that really a fix? Consider that the square root of 47 is 6.8556546004 . but squareRoot will get the value 6 . (The conversion will truncate, not round.)

And what about this?

That results in b getting the value 0 . Converting from a larger int type to a smaller int type is done by masking out the high order bits, and the low-order 8 bits of 512 are all zero.

In short, you should not simply add a typecast, because it might not do the correct thing for your application.

Instead, you need to understand why your code needs to do a conversion:

  • Is this happening because you have made some other mistake in your code?
  • Should the be a different type, so that a lossy conversion isn’t needed here?
  • If a conversion is necessary, is the silent lossy conversion that the typecast will do the correct behavior?
  • Or should your code be doing some range checks and dealing with incorrect / unexpected values by throwing an exception?

«Possible lossy conversion» when subscripting.

The problem here is that array index value must be int . So d has to be converted from double to int . In general, using a floating point value as an index doesn’t make sense. Either someone is under the impression that Java arrays work like (say) Python dictionaries, or they have overlooked the fact that floating-point arithmetic is often inexact.

The solution is to rewrite the code to avoid using a floating point value as an array index. (Adding a type cast is probably an incorrect solution.)

This is a variation of the previous problem, and the solution is the same. The difference is that the root cause is that Java arrays are limited to 32 bit indexes. If you want an «array like» data structure which has more than 2 31 — 1 elements, you need to define or find a class to do it.

«Possible lossy conversion» in method or constructor calls

Compiling the above with Java 11 gives the following:

The problem is that the literal 20 is an int , and the corresponding parameter in the constructor is declared as a short . Converting an int to a short is lossy.

«Possible lossy conversion» in a return statement.

A return (with a value / expression) could be thought of an an «assignment to the return value». But no matter how you think about it, it is necessary to convert the value supplied to the actual return type of the method. Possible solutions are adding a typecast (which says «I acknowledge the lossy-ness») or changing the method’s return type.

This will tell you that you that there is a «possible lossy conversion from int to byte». This is actually a variation of the first example. The potentially confusing thing is understanding where the int comes from.

The answer to that is it comes from the & operator. In fact all of the arithmetic and bitwise operators for integer types will produce an int or long , depending on the operands. So in the above example, b1 & mask is actually producing an int , but we are trying to assign that to a byte .

To fix this example we must type-cast the expression result back to a byte before assigning it.

«Possible lossy conversion» when assigning literals

What is going on? Why is one version allowed but the other one isn’t? (After all they «do» the same thing!)

First of all, the JLS states that 21 is an numeric literal whose type is int . (There are no byte or short literals.) So in both cases we are assigning an int to a byte .

In the first case, the reason for the error is that not all int values will fit into a byte .

In the second case, the compiler knows that 21 is a value that will always fit into a byte .

The technical explanation is that in an assignment context, it is permissible to perform a primitive narrowing conversion to a byte , char or short if the following are all true:

  • The value is the result of a compile time constant expression (which includes literals).
  • The type of the expression is byte , short , char or int .
  • The constant value being assigned is representable (without loss) in the domain of the «target» type.

Note that this only applies with assignment statements, or more technically in assignment contexts. Thus:

gives a compilation error.

1 — For instance, the Eclipse IDE has an option which allows you to ignore compilation errors and run the code anyway. If you select this, the IDE’s compiler will create a .class file where the method with the error will throw an unchecked exception if it is called. The exception message will mention the compilation error message.

Источник

Possible lossy conversion from double to float, given float values? [duplicate]

if i’m not mistaken, «0.5» are decimal numbers; thus, making it a float value. but why is java telling me that it is a double?. the return statements are detected as errors by java, saying: «incompatible types:possible lossy conversion from double to float»

4 Answers 4

If I’m not mistaken, 0.5 are decimal numbers; thus, making it a float value.

You should not rely solely on your intuition when learning a new programming language.

In fact, 0.5 is a double literal. For a float literal you need to write 0.5f .

As The Java Language Specification (JLS 3.10.2) states:

A floating-point literal is of type float if it is suffixed with an ASCII letter F or f ; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d .

You have two options.

One is change your method’s return type to double.

The other is change the double values you are returning to float values, as many have said in the comments.

In java, we have float and double as floating point literals, where double is the default data type of floating point literals and not the float. This is the reason why java is telling you that 0.5 is a double.

Possible conversion:

1) float a = (float) 0.5;

And reason for lossy conversion is because, double is bigger than float. When you try to fit-in the bigger one into the smaller one, you will get this error.

Источник

getting error: incompatible types: possible lossy conversion from double to float for type promotion code

i didnt understand the error when executing below code.

Main.java:7: error: incompatible types: possible lossy conversion from double to float float f = 9.987; ^ Main.java:9: error: incompatible types: possible lossy conversion from double to int int res = (fb) + (i/c) — (ds); ^ 2 errors

2 Answers 2

I guess you are beginner in java . So the mistake you are making is typecasting . You can not assign double value to a float type .

If you don’t want to face this problem again in future learn about type casting (automatic conversion and explicit conversion).

The result of an operation between different data types will always be the largest type (here double). If you want to keep the result as an int : look into casting values.

It should look like this : int res = (int) ((f*b) + (i/c) — (d*s))

Otherwise, make the result a double.

Also, floats in java need to have f at the end : float f = 9.987f;

Linked

Hot Network Questions

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.1.14.43159

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

How to Handle the Incompatible Types Error in Java

Table of Contents

Introduction to Data Types & Type Conversion

Variables are memory containers used to store information. In Java, every variable has a data type and stores a value of that type. Data types, or types for short, are divided into two categories: primitive and non-primitive. There are eight primitive types in Java: byte , short , int , long , float , double , boolean and char . These built-in types describe variables that store single values of a predefined format and size. Non-primitive types, also known as reference types, hold references to objects stored somewhere in memory. The number of reference types is unlimited, as they are user-defined. A few reference types are already baked into the language and include String , as well as wrapper classes for all primitive types, like Integer for int and Boolean for boolean . All reference types are subclasses of java.lang.Object [1].

In programming, it is commonplace to convert certain data types to others in order to allow for the storing, processing, and exchanging of data between different modules, components, libraries, APIs, etc. Java is a statically typed language, and as such has certain rules and constraints in regard to working with types. While it is possible to convert to and from certain types with relative ease, like converting a char to an int and vice versa with type casting [2], it is not very straightforward to convert between other types, such as between certain primitive and reference types, like converting a String to an int , or one user-defined type to another. In fact, many of these cases would be indicative of a logical error and require careful consideration as to what is being converted and how, or whether the conversion is warranted in the first place. Aside from type casting, another common mechanism for performing type conversion is parsing [3], and Java has some predefined methods for performing this operation on built-in types.

Incompatible Types Error: What, Why & How?

The incompatible types error indicates a situation where there is some expression that yields a value of a certain data type different from the one expected. This error implies that the Java compiler is unable to resolve a value assigned to a variable or returned by a method, because its type is incompatible with the one declared on the variable or method in question. Incompatible, in this context, means that the source type is both different from and unconvertible (by means of automatic type casting) to the declared type.

This might seem like a syntax error, but it is a logical error discovered in the semantic phase of compilation. The error message generated by the compiler indicates the line and the position where the type mismatch has occurred and specifies the incompatible types it has detected. This error is a generalization of the method X in class Y cannot be applied to given types and the constructor X in class Y cannot be applied to given types errors discussed in [4].

The incompatible types error most often occurs when manual or explicit conversion between types is required, but it can also happen by accident when using an incorrect API, usually involving the use of an incorrect reference type or the invocation of an incorrect method with an identical or similar name.

Incompatible Types Error Examples

Explicit type casting

Assigning a value of one primitive type to another can happen in one of two directions. Either from a type of a smaller size to one of a larger size (upcasting), or from a larger-sized type to a smaller-sized type (downcasting). In the case of the former, the data will take up more space but will be intact as the larger type can accommodate any value of the smaller type. So the conversion here is done automatically. However, converting from a larger-sized type to a smaller one necessitates explicit casting because some data may be lost in the process.

Fig. 1(a) shows how attempting to assign the values of the two double variables a and b to the int variables x and y results in the incompatible types error at compile-time. Prefixing the variables on the right-hand side of the assignment with the int data type in parenthesis (lines 10 & 11 in Fig. 1(b)) fixes the issue. Note how both variables lost their decimal part as a result of the conversion, but only one kept its original value—this is exactly why the error message reads possible lossy conversion from double to int and why the incompatible types error is raised in this scenario. By capturing this error, the compiler prevents accidental loss of data and forces the programmer to be deliberate about the conversion. The same principle applies to downcasting reference types, although the process is slightly different as polymorphism gets involved [5].

Источник

Автор оригинала: baeldung.

1. Обзор

В этом кратком руководстве мы обсудим концепцию преобразования с потерями в Java и причину этого.

В то же время мы рассмотрим некоторые удобные методы преобразования, чтобы избежать этой ошибки.

2. Преобразование С Потерями

Преобразование с потерями-это просто потеря информации при обработке данных.

В Java это соответствует возможности потери значения или точности переменной при преобразовании одного типа в другой.

Когда мы пытаемся назначить переменную типа большого размера типу меньшего размера , Java генерирует ошибку, несовместимые типы: возможное преобразование с потерями , при компиляции кода.

Например, давайте попробуем назначить long для int :

long longNum = 10;
int intNum = longNum;

Java выдаст ошибку при компиляции этого кода:

incompatible types: possible lossy conversion from long to int

Здесь Java найдет long и int несовместимыми и приведет к ошибке преобразования с потерями. Потому что могут быть длинные значения за пределами int диапазона от -2,147,483,648 до 2,147,483,647.

Аналогично, давайте попробуем назначить float a long :

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

Поскольку float может иметь десятичные значения, которые не имеют соответствующего long значения. Поэтому мы получим ту же ошибку.

Аналогично, присвоение double номера int приведет к той же ошибке:

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

Значения double могут быть слишком большими или слишком маленькими для int , и десятичные значения будут потеряны при преобразовании. Следовательно, это потенциальное преобразование с потерями.

Кроме того, мы можем столкнуться с этой ошибкой при выполнении простого вычисления:

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

Когда double умножается на int , мы получаем результат в double . Следовательно, это также потенциальное преобразование с потерями.

Поэтому несовместимые типы в преобразовании с потерями могут иметь разные размеры или типы (целые или десятичные числа).

3. Примитивные Типы данных

В Java существует множество примитивных типов данных, доступных с соответствующими классами-оболочками .

Далее давайте составим удобный список всех возможных преобразований с потерями в Java:

  • short to byte или char
  • char to байт или короткий
  • int to byte , short или char
  • long to byte , short , char или int
  • float to byte , short , char , int или long
  • double to byte , short , char , int , long или float

Обратите внимание, что хотя short и char имеют одинаковый размер. Тем не менее, преобразование из short в char приводит к потерям, поскольку char является типом данных без знака .

4. Методы преобразования

4.1. Преобразование Между Примитивными Типами

Простой способ преобразования примитивов, чтобы избежать преобразования с потерями,-это понижение; другими словами, приведение типа большего размера к типу меньшего размера. Следовательно, это также называется сужением примитивного преобразования.

Например, давайте преобразуем длинное число в короткое с помощью понижающей передачи :

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

Аналогично, давайте преобразуем double в int :

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

Однако следует отметить, что преобразование типа большого размера со слишком большими или слишком маленькими значениями в тип меньшего размера с помощью понижения может привести к неожиданным значениям.

Давайте преобразуем длинные значения за пределами диапазона короткие :

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

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

Если мы внимательно проанализируем конверсию, то увидим, что это не ожидаемые значения.

Другими словами, когда Java достигает наибольшего значения типа малого размера при преобразовании из типа большого размера, следующее число является наименьшим значением типа малого размера и наоборот.

Давайте разберемся в этом на примерах. Когда большое длинное число со значением 32768 преобразуется в короткое , значение короткое число 1 равно -32768 . Поскольку максимальное значение short равно 32767, поэтому Java переходит к следующему минимальному значению short.

Аналогично, когда маленькое длинное число преобразуется в короткое . Значение short Num2 равно 32767, поскольку Java переходит к следующему максимальному значению short .

Кроме того, давайте посмотрим, что произойдет, когда мы преобразуем максимальные и минимальные значения a 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. Преобразование между объектами-оболочками и примитивными типами

Чтобы напрямую преобразовать объект-оболочку в примитив, мы можем использовать различные методы в классах-оболочках, такие как int Value () , shortValue() и longValue() . Это называется распаковка .

Например, давайте преобразуем объект Float в объект long :

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

Кроме того, если мы посмотрим на реализацию long Value или аналогичных методов, мы найдем применение сужающего примитивного преобразования:

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

Однако иногда следует избегать сужения примитивного преобразования, чтобы сохранить ценную информацию:

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

После преобразования значение long Num будет равно 15. Однако двойное число равно 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);

Наконец, мы используем Integer . valueOf() для преобразования примитивного типа int в Целое число объект. Этот тип преобразования называется boxing .

5. Заключение

В этой статье мы исследовали концепцию преобразования с потерями в Java с помощью ряда примеров. Кроме того, мы также составили удобный список всех возможных конверсий с потерями.

Попутно мы определили сужение примитивного преобразования как простой метод преобразования примитивных чисел и избежания ошибки преобразования с потерями.

В то же время мы также изучили дополнительные удобные методы числовых преобразований в Java.

Реализации кода для этой статьи можно найти на GitHub .

Introduction to Data Types & Type Conversion

Variables are memory containers used to store information. In Java, every variable has a data type and stores a value of that type. Data types, or types for short, are divided into two categories: primitive and non-primitive. There are eight primitive types in Java: byte, short, int, long, float, double, boolean and char. These built-in types describe variables that store single values of a predefined format and size. Non-primitive types, also known as reference types, hold references to objects stored somewhere in memory. The number of reference types is unlimited, as they are user-defined. A few reference types are already baked into the language and include String, as well as wrapper classes for all primitive types, like Integer for int and Boolean for boolean. All reference types are subclasses of java.lang.Object [1].

In programming, it is commonplace to convert certain data types to others in order to allow for the storing, processing, and exchanging of data between different modules, components, libraries, APIs, etc. Java is a statically typed language, and as such has certain rules and constraints in regard to working with types. While it is possible to convert to and from certain types with relative ease, like converting a char to an int and vice versa with type casting [2], it is not very straightforward to convert between other types, such as between certain primitive and reference types, like converting a String to an int, or one user-defined type to another. In fact, many of these cases would be indicative of a logical error and require careful consideration as to what is being converted and how, or whether the conversion is warranted in the first place. Aside from type casting, another common mechanism for performing type conversion is parsing [3], and Java has some predefined methods for performing this operation on built-in types.

double myDouble = 9; // Automatic casting (int to double)
int myInt = (int) 9.87d; // Manual casting (double to int)
boolean myBoolean = Boolean.parseBoolean("True"); // Parsing with a native method (String to boolean)

System.out.println(myDouble);   // 9.0
System.out.println(myInt);      // 9
System.out.println(myBoolean);  // true

Incompatible Types Error: What, Why & How?

The incompatible types error indicates a situation where there is some expression that yields a value of a certain data type different from the one expected. This error implies that the Java compiler is unable to resolve a value assigned to a variable or returned by a method, because its type is incompatible with the one declared on the variable or method in question. Incompatible, in this context, means that the source type is both different from and unconvertible (by means of automatic type casting) to the declared type.

This might seem like a syntax error, but it is a logical error discovered in the semantic phase of compilation. The error message generated by the compiler indicates the line and the position where the type mismatch has occurred and specifies the incompatible types it has detected. This error is a generalization of the method X in class Y cannot be applied to given types and the constructor X in class Y cannot be applied to given types errors discussed in [4].

The incompatible types error most often occurs when manual or explicit conversion between types is required, but it can also happen by accident when using an incorrect API, usually involving the use of an incorrect reference type or the invocation of an incorrect method with an identical or similar name.

Incompatible Types Error Examples

Explicit type casting

Assigning a value of one primitive type to another can happen in one of two directions. Either from a type of a smaller size to one of a larger size (upcasting), or from a larger-sized type to a smaller-sized type (downcasting). In the case of the former, the data will take up more space but will be intact as the larger type can accommodate any value of the smaller type. So the conversion here is done automatically. However, converting from a larger-sized type to a smaller one necessitates explicit casting because some data may be lost in the process.

Fig. 1(a) shows how attempting to assign the values of the two double variables a and b to the int variables x and y results in the incompatible types error at compile-time. Prefixing the variables on the right-hand side of the assignment with the int data type in parenthesis (lines 10 & 11 in Fig. 1(b)) fixes the issue. Note how both variables lost their decimal part as a result of the conversion, but only one kept its original value—this is exactly why the error message reads possible lossy conversion from double to int and why the incompatible types error is raised in this scenario. By capturing this error, the compiler prevents accidental loss of data and forces the programmer to be deliberate about the conversion. The same principle applies to downcasting reference types, although the process is slightly different as polymorphism gets involved [5].

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package rollbar;

public class IncompatibleTypesCasting {

  public static void main(String... args) {
    double a = 10.5;
    double b = 5.0;
    System.out.println("a: " + a + "tb: " + b);

    int x = a;
    int y = b;
    System.out.println("x: " + x + "ty: " + y);
  }
}
IncompatibleTypesCasting.java:10: error: incompatible types: possible lossy conversion from double to int
    int x = a;
            ^
IncompatibleTypesCasting.java:11: error: incompatible types: possible lossy conversion from double to int
    int y = b;
            ^
2 errors

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package rollbar;

public class IncompatibleTypesCasting {

  public static void main(String... args) {
    double a = 10.5;
    double b = 5.0;
    System.out.println("a: " + a + "tb: " + b);

    int x = (int) a;
    int y = (int) b;
    System.out.println("x: " + x + "ty: " + y);
  }
}
a: 10.5 b: 5.0
x: 10   y: 5
Figure 1: Incompatible types when downcasting (a) error and (b) resolution

Explicit parsing

Parsing is a more complex process than type casting as it involves analyzing the underlying structure of a given data before converting it into a specific format or type. For instance, programmers often deal with incoming streams of characters, usually contained in a string that needs to be converted into specific types to make use of in the code. A common scenario is extracting numeric values from a string for further processing, which is where parsing is routinely used.

The main method in Fig. 2(a) declares the variable date which holds the current date as a String in the yyyy-MM-dd format. In order to get the year value into a separate variable it is necessary to “parse” the first 4 characters of the string, and this can be accomplished by splitting the string by specifying the “-” character as a delimiter and then accessing the first element (line 9 in Fig. 2(a)). With this, the year value has been successfully parsed and stored into a new variable. Attempting to increase the value of this new variable and store the resulting value in a separate int variable triggers the incompatible types error (line 10 in Fig. 2(a)). This is because even though the year has been isolated from the date and parsed into a new variable, it is impossible to perform arithmetic operations on a variable of type String. Therefore, it is necessary to represent this value as a numeric type. The best way to do this is to use Java’s built-in Integer::parseInt method which takes a String argument and converts it to an int (line 10 in Fig. 2(b)). (Note that if the given argument is not a valid integer value, this method will throw an exception.) Now that the year has been manually and explicitly parsed from the initial date string into an integer value that can be incremented, the program compiles and prints the expected message, as shown in Fig. 2(b).

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

import java.time.LocalDate;

public class IncompatibleTypesParsing {

 public static void main(String... args) {
   String date = LocalDate.now().toString(); // "2021-12-21"
   String year = date.split("-")[0]; // "2021"
   int newYear = year + 1;
   System.out.println("Happy New Year " + newYear + "!");
 }
}
IncompatibleTypesParsing.java:10: error: incompatible types: String cannot be converted to int
    int newYear = year + 1;
                       ^
1 error

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

import java.time.LocalDate;

public class IncompatibleTypesParsing {

  public static void main(String... args) {
    String date = LocalDate.now().toString();
    String year = date.split("-")[0];
    int newYear = Integer.parseInt(year) + 1;
    System.out.println("Happy New Year " + newYear + "!");
  }
}
Happy New Year 2022!
Figure 2: Incompatible types when parsing (a) error and (b) resolution

Incorrect type assignments

Sometimes, the incompatible types error can occur due to basic negligence, where the only mistake is an accidental mis-declaration of a variable’s type (Fig. 3(a)). In these instances, the issue is quite obvious and simply correcting the type declaration solves the problem (Fig. 3(b)).

(a)

package rollbar;

public class IncompatibleTypesAssignment {

 public static void main(String... args) {
   int greeting = "Merry Christmas!";
   System.out.println(greeting);
 }
}
IncompatibleTypesAssignment.java:6: error: incompatible types: String cannot be converted to int
    int greeting = "Merry Christmas!";
                   ^
1 error

(b)

package rollbar;

public class IncompatibleTypesAssignment {

 public static void main(String... args) {
   String greeting = "Merry Christmas!";
   System.out.println(greeting);
 }
}
Merry Christmas!
Figure 3: Incompatible types with incorrect assignment (a) error and (b) resolution

Incorrect method return types

A slightly less common but non-surprising occurence of the incompatible types error, especially when refactoring is involved, can be found in method return types. Namely, sometimes a method’s return statement ends up returning a value that doesn’t match the method’s declared return type (Fig. 4(a)). This issue has two possible remedies; either make the value returned match the return type (Fig. 4(b)), or change the method’s return type to match the actual value returned (Fig. 4(c)). And in the case of void methods (methods with no return type), one can simply get rid of the return statement if the return value is never used, as is the case with the example in Fig. 4.

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

public class IncompatibleTypesReturn {

 public static void main(String... args) {
   printGreeting();
 }

 static void printGreeting() {
   System.out.println("Happy Holidays");
   return true;
 }
}
IncompatibleTypesReturn.java:11: error: incompatible types: unexpected return value
    return true;
           ^
1 error

(b)

1
2
3
4
5
6
7
8
9
10
11
12
package rollbar;

public class IncompatibleTypesReturn {

 public static void main(String... args) {
   printGreeting();
 }

 static void printGreeting() {
   System.out.println("Happy Holidays");
 }
}
Happy Holidays!

(c)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

public class IncompatibleTypesReturn {

 public static void main(String... args) {
   printGreeting();
 }

 static boolean printGreeting() {
   System.out.println("Happy Holidays");
   return true;
 }
}
Happy Holidays!
Figure 4: Incompatible types with incorrect return type (a) error and (b)(c) two solutions

Incorrect imports and similarly named reference types

It is not uncommon to come across classes or other reference types with the same or a similar name. In fact, this happens even within the standard Java API, and can baffle many programmers, beginners and experts alike. One such case is the List class which represents one of Java’s main collection data structures [6]. This reference type can easily come into collision with another type of the same name, but from a different package. Namely, that’s the java.awt.List class that is part of Java’s built-in AWT API for creating graphical user interfaces [7]. All it takes is accidentally importing the wrong package, and the compiler immediately complains about the type mismatch, raising the incompatible types error, as demonstrated in Fig. 5(a). Fixing the import on line 5, as shown in Fig. 5(b), sorts things out.

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

import java.util.ArrayList;
import java.util.Arrays;
import java.awt.List;

public class IncompatibleTypesList {

 public static void main(String... args) {
   List songs = new ArrayList<String>(Arrays.asList("Silent Night", "Deck the Halls", "Jingle Bells", "Winter Wonderland"));
   System.out.println(songs);
 }
}
IncompatibleTypesList.java:10: error: incompatible types: ArrayList<String> cannot be converted to List
    List songs = new ArrayList<String>(Arrays.asList("Silent Night", "Deck the Halls", "Jingle Bells", "Winter Wonderland"));
                 ^
1 error

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
package rollbar;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class IncompatibleTypesList {

 public static void main(String... args) {
   List songs = new ArrayList<String>(Arrays.asList("Silent Night", "Deck the Halls", "Jingle Bells", "Winter Wonderland"));
   System.out.println(songs);
 }
}
[Silent Night, Deck the Halls, Jingle Bells, Winter Wonderland]
Figure 5: Incompatible types incorrect reference type (a) error and (b) resolution

Popular external libraries are also prone to naming their reference types similarly, so whenever relying on such a library for a certain feature or functionality it is important to pick one, or be careful not to confuse one for another, if multiple libraries are already being used.

Fig. 6(a) shows an example of passing a JSON type object to a method as an argument. Here, the method printJson expects an argument of type JsonObject, but the calling method tries to pass in an instance of the similarly named JSONObject reference type, part of a different library altogether. This results in the incompatible types error being raised by the compiler, with the alert org.json.JSONObject cannot be converted to javax.json.JsonObject pointing to the erroneous method call. Swapping the inappropriate constructor call with an instance of the correct type solves the issue, as shown in Fig. 6(b).

(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package rollbar;

import org.json.JSONObject;
import javax.json.JsonObject;
import java.util.Map;

public class IncompatibleTypesJson {

  public static void main(String... args) {
    Map<String, Object> jsonMap = Map.of(
        "name", "Saint Nicholas",
        "nicknames", new String[]{"Santa Claus", "Father Christmas"},
        "location", "North Pole"
    );

    JsonObject json = Json.createObjectBuilder(jsonMap).build();

    printJson(json);
}

  static void printJson(JSONObject jsonObject) {
    System.out.println(jsonObject.toString(4));
  }
}
IncompatibleTypesJson.java:18: error: incompatible types: 
javax.json.JsonObject cannot be converted to org.json.JSONObject
    printJson(json);
              ^

(b)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package rollbar;

import javax.json.Json;
import javax.json.JsonObject;
import java.util.Map;

public class IncompatibleTypesJson {

  public static void main(String... args) {
    Map<String, Object> jsonMap = Map.of(
        "name", "Saint Nicholas",
        "nicknames", new String[]{"Santa Claus", "Father Christmas"},
        "location", "North Pole"
    );

    JSONObject json = new JSONObject(jsonMap);

    printJson(json);
  }

  static void printJson(JSONObject jsonObject) {
    System.out.println(jsonObject.toString(4));
  }
}
{
    "name": "Saint Nicholas",
    "location": "North Pole",
    "nicknames": [
        "Santa Claus",
        "Father Christmas"
    ]
}
Figure 6: Incompatible types incorrect reference type (a) error and (b) resolution

Fig. 6 also serves as an example to show how the incompatible types error is, in fact, a generalization of the method X in class Y cannot be applied to given types error explored in [4]. Depending on the specific compiler that is being used and its configuration settings, either of these errors could be triggered in this kind of scenario.

Summary

As a strongly typed language, Java has strict rules regarding data types and how they interoperate. These rules affect variable assignment, method invocation, return values, etc. This makes Java code verbose, but at the same time quite secure, as it allows for many errors to be detected during compilation. One such error is the incompatible types error, which is directly tied to Java’s type system. This article provides some background into Java types and dives into the symptoms and causes behind the incompatible types error, by presenting a series of relevant examples tailored to bring clarity in understanding and successfully managing this error.

Track, Analyze and Manage Errors With Rollbar

Rollbar in action

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

References

[1] R. Liguori and P. Liguori, 2017. Java Pocket Guide, 4th ed. Sebastopol, CA: O’Reilly Media, pp. 23-46.

[2] W3schools.com, 2021. Java Type Casting. Refsnes Data. [Online]. Available: https://www.w3schools.com/java/java_type_casting.asp. [Accessed: Dec. 18, 2021]

[3] D. Capka, 2021. Lesson 3 — Variables, type system and parsing in Java, Ictdemy.com. [Online]. Available: https://www.ictdemy.com/java/basics/variables-type-system-and-parsing-in-java. [Accessed: Dec. 19, 2021]

[4] Rollbar, 2021. How to Fix Method/Constructor X in Class Y Cannot be Applied to Given Types in Java, Rollbar Editorial Team. [Online]. Available: https://rollbar.com/blog/how-to-fix-method-constructor-in-class-cannot-be-applied-to-given-types-in-java/. [Accessed: Dec. 21, 2021]

[5] W3schools.com, 2021. Java Type Casting. Refsnes Data. [Online]. Available: https://www.w3schools.com/java/java_type_casting.asp. [Accessed: Dec. 21, 2021]

[6] Oracle.com, 2021. Lesson: Implementations (The Java™ Tutorials > Collections). [Online]. Available: https://docs.oracle.com/javase/tutorial/collections/implementations/index.html. [Accessed: Dec. 21, 2021]

[7] Oracle.com, 2020. Package java.awt (Java SE 15 & JDK 15). Oracle and/or its affiliates [Online]. Available: https://docs.oracle.com/en/java/javase/15/docs/api/java.desktop/java/awt/package-summary.html. [Accessed: Dec. 21, 2021]

1. Overview

In this quick tutorial, we’ll discuss the concept of lossy conversion in Java and the reason behind it.

At the same time, we’ll explore some handy conversion techniques to avoid this error.

2. Lossy Conversion

Lossy conversion is simply the loss of information while handling data.*
*

In Java, it corresponds to the possibility of losing the value or precision of a variable while converting one type to another.

When we try to assign a variable of large-sized type to a smaller sized type, Java will generate an error, incompatible types: possible lossy conversion, while compiling the code.

For example, let’s try to assign a long to an int:

long longNum = 10;
int intNum = longNum;

Java will emit an error while compiling this code:

incompatible types: possible lossy conversion from long to int

Here, Java will find long and int incompatible and result in lossy conversion error. Because there can be long values outside the int range -2,147,483,648 to 2,147,483,647.

Similarly, let’s try to assign a float to a long:

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

As float can have decimal values that don’t have corresponding long value. Therefore, we’ll receive the same error.

Similarly, assigning a double number to an int will cause the same error:

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

The double values can be too large or too small for an int and decimal values will get lost in the conversion. Hence, it is a potential lossy conversion.

Also, we can run into this error while performing a simple calculation:

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

When a double multiply with an int, we get the result in a double. Consequently, it is also a potential lossy conversion.

Therefore, the incompatible types in lossy conversion can either have different sizes or types (integers or decimals).*
*

3. Primitive Data Types

Next, let’s compile a handy list of all possible lossy conversions in Java:

  • short to byte or char

  • char to byte or short

  • int to byte, short or char

  • long to byte, short, char or int

  • float to byte, short, char, int or long

  • double to byte, short, char, int, long or float

Note that though short and char have the same size. Still, the conversion from short to char is lossy because char is an unsigned data type.

4. Conversion Techniques

==== 4.1. Converting Between Primitive Types

The easy way of converting primitives to avoid lossy conversion is through downcasting; in other words, casting the larger-sized type to a smaller-sized type. Hence, it is also called narrowing primitive conversion.

For instance, let’s convert a long number to a short using downcasting:

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

Similarly, let’s convert a double to an int:

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

However, we should note that converting large-sized type with values too large or too small to smaller-sized type through downcasting can result in unexpected values.

Let’s convert long values outside the range of short:

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

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

If we carefully analyze the conversion, we’ll see that these are not the expected values.

In other words, when Java hits the highest value of a small-sized type while converting from large-sized type, the next number is the lowest value of the small-sized type and vice-versa.

Let’s understand this through examples. When largeLongNum with the value of 32768 is converted to short, the value of shortNum1 is -32768. Because the max value of short is 32767, therefore, Java goes for the next min value of the short.

Similarly, when smallLongNum is converted to short. The value of shortNum2 is 32767 as Java goes for the next max value of the short.

Also, let’s see what happens when we convert the max and min values of a long to an 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. Converting Between Wrapper Objects and Primitive Types

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.

Click on the blue words in the upper left corner and follow “Big Guy outside the pot”

Focus on sharing the latest foreign technology content

1. An overview of the
In this quick tutorial, we’ll discuss the concept of lossy transformations in Java and the reasons behind them.
In the meantime, we’ll explore some convenient transformation techniques to avoid this error.
2. Lossy conversion
Lossy transformation is the loss of information while processing data.
In Java, this corresponds to the possibility of losing variable values or precision when converting from one type to another.
When we try to convert a variable of a high-level type to a low-level type, Java will generate an incorrect, incompatible type when compiling the code: a potentially lossy conversion.
For example, let’s try assigning a long value to an int value:

long longNum = 10;	
int intNum = longNum;

When compiling this code, Java produces an error:

incompatible types: possible lossy conversion from long to int

Here, Java will find that long and int are incompatible and cause lossy conversion errors. Because you can have long values outside of the int range of -2,147,483,648 to 2,147,483,647.
Similarly, we try to assign a long to a float:

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

Because floats can represent small values that don’t have a corresponding long type. Therefore, we will receive the same error.
Similarly, converting a double to an int results in the same error:

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

The double value may be too large or too small for an int value, and the small value will be lost in the conversion. Therefore, this is a potentially lossy transformation.
In addition, we may encounter this error when performing a simple calculation:

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

When a double is multiplied by an int, the result is a double. Therefore, it is also a potentially lossy transformation.
Therefore, incompatible types in lossy conversions can have different sizes or types (integer or decimal).
3. Basic data types
In Java, there are many basic data types and their corresponding wrapper classes.
Next, let’s make a list of all possible lossy transformations in Java:
short to byte or charchar to byte or shortint to byte, short or charlong to byte, short, char or intfloat to byte, short, char, int or longdouble to byte, short, char, int, long or float
Note that although short and CHAR have the same range. However, the conversion from short to char is lossy because char is an unsigned data type.
4. Transform technology
4.1. Conversion between two basic data types
The simple way to avoid lossy conversions for primitive types is by casting down; In other words, cast a high-level type to a low-level type. For this reason, it is also called a narrowing primitive conversion.
For example, let’s convert long to short using a downward cast:

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

Similarly, convert a double to an int:

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

However, we should note that casting down a high-level type with a value too large or too small to a low-level type can result in unexpected values.
We convert a long value to a value outside the range of the short type:

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

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

If we look closely at the transformations, we see that these are not the expected values.
In other words, when Java is converting from a high-level type to a low-level type, when the maximum value of the low-level type is reached, the next value is the minimum value of the low-level type, and vice versa.
Let’s look at an example to understand this. When largeLongNum with a value of 32768 is converted to short, the value of shortNum1 is -32768. Since the maximum value of short is 32767, Java will select the next minimum value of short.
Similarly, when smallLongNum is converted to short. ShortNum2 has a value of 32767, which Java USES as the next maximum for Short.
Also, let’s look at what happens when we convert the maximum and minimum values of long to ints:

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. Convert between wrapper objects and primitive types
To convert the wrapper object directly to the base type, we can use various methods in the wrapper class, such as intValue(), shortValue(), and longValue(). This is called unpacking.
For example, let’s convert a Float object to a long:

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

In addition, if we look at the implementation of longValue or similar methods, we will find the use of narrowing the original transformation:

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

However, sometimes you should avoid narrowing the original transformation to preserve valuable information:

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

After conversion, the value of longNum is 15. However, doubleNum is 15.9999, very close to 16.
Instead, we can use math. round() to convert to the nearest integer:

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

4.3. Convert between wrapper objects
To do this, let’s use the transformation techniques we’ve already discussed.
First, we will convert the wrapper object to a base value, cast it down and convert it to another wrapper object. In other words, we will perform unboxing, downcast, 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);

Finally, we use intet.valueof () to convert the basic type int to an Integer object. This type of conversion is called boxing.
5. To summarize
In this article, we explored the concept of lossy transformations in Java through examples. In addition, we have written a handy list of all possible lossy transformations in Java.
Along the way, we’ve determined that narrowing the original transform is an easy way to transform the base type and avoid lossy conversion errors.
At the same time, we explored other convenient techniques for numeric conversion in Java.
The code implementation for this article can be found on the GitHub project.  
From spring for All community Translation group


Recently, I have translated the articles into PDF.
Reply in the background of official account: 002 can get oh ~
The content of PDF will be updated continuously in the future, please look forward to it!

● Top 10 mistakes you make using the Spring Framework
● Why Spring as the Java framework?
●Solr full-text search
Top right button to share with more people ~

Here we are. Click and watch before you go


posted 6 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

Daniel Cox wrote:

Julian West wrote:…with «possible loss of precision»

From information I gathered in this thread, since integer division always discards the fractional part, you cannot say that integer division results in «loss of precision». You can say that integer division results in «loss of information» (which is worse than «loss of precision»). Precision comes into play with datatypes that have fractional parts. Precision is about how close measured values are to each other. So if you take multiple double measurements, you will get higher precision than multiple float measurements.

Campbell Ritchie wrote:

Ganesh Patekar wrote:. . .  results var = 2 because var/4 means 10 /4  which results 2 where we lost precision i.e. 0.5 because both diviser and dividend are int. . . .

I am not sure I would call that loss of precision.

You quoted me out of context, missing my point.  To clarify:

If the compiler didn’t force us to explicitly promote integers to doubles as the OP discussed, then we wouldn’t be able to do integer division implicitly but instead, would give us the «possible lossy conversion» incompatible types compiler error like the following does:

If stuffing a double-precision floating point fraction into a single-precision floating point variable is a loss of precision, then certainly stuffing the same double-precision fraction into a zero-precision fraction (integer) is a greater loss of precision.

Precision is an attribute of information.  I could say that a new flux capacitor costs $30K, $32K, $32-seven, $32,768, or $32,768.16.  It’s the same information, just with different precision.  A hallway conversation wouldn’t warrant two-place-decimal point precision but the person disbursing payment does.

Implicitly, java math is all integers, so 10/4=2; the fraction isn’t dropped because it was never there in the first place because we’re only dealing with ints until explicitly specified otherwise; hence…

…is the same as…

…both yield 0.0 since there were never any fractions.  «I bought two flux capacitors @ $30K each; I spent $60K.»

If the compiler weren’t designed this way, then we would have to explicitly cast (int) whenever we’re doing simple integer division since the potential for fractions will always exist, making the «possible lossy conversion» always an issue.

I say all this not just for semantics but to understand—heh, precisely—what is going on and why rather than to advocate relying on memory to pass the exam and to not want to punch the compiler in the face when things don’t seem to make sense.

Понравилась статья? Поделить с друзьями:
  • Error incompatible types in assignment
  • Error incompatible types got single expected smallint
  • Error incompatible types got real expected smallint
  • Error incompatible types got extended expected smallint
  • Error incompatible types got extended expected longint