Understanding "possible loss of precision required char found byte" - java

class A {
public static void main(String [] varun) {
byte b = 65;
char ch = b;
System.out.println(ch);
}
}
Why its give an error:
possible loss of precision
required char
found byte

The error text is misleading.
A char is a 2 byte unsigned type (range 0 to 65535)
A byte is a 1 byte signed type (range -128 to 127).
Therefore a byte cannot be represented in a char in full generality (as you'll lose the negatives). So you get an error; albeit a misleading one.

Byte is 1 byte long, while char is 2 bytes long, so they are incompatible. You need to use casting:
class A
{
public static void main(String [] varun)
{
byte b = 65;
char ch = (char) b;
System.out.println(ch);
}
}

Add as explicit cast as byte just take one byte and char is of two byte in java and implicit type cast does not work with byte and char.
Use
char ch = (char) b;

Your code should be like this:
char ch = (char) b;
The error it gave you it became from the fact that a byte type is an 8-bit integers and chars is 1-bit plus the bits of encoding (UTF-8, ASCII, etc).
The difference between a byte stream and a character stream is that the character stream attempts to work with characters rather than bytes.
So a byte stream is 8-bit stream without encoding. That's why you have this error.

If You are assigned two different type of primitives to each other You may have two types of casting:
if You assign int to long, thus putting smaller type into bigger You perform widening and so called widening conversion - it is also called implicit cast
int a = 100;
long b = a;
on the other hand if You would perform conversion from long to int You are narrowing the type. Thus You need to perform explicit cast if You don't do that You get that possible loss of precision
long a = 100L;
int b = (int)a;
or as in Your case as #Bathsheba said "Therefore a byte cannot be represented in a char in full generality (as you'll lose the negatives). So you get an error; albeit a misleading one." - You need to explicitly cast so that You are aware of loosing data.

When one type of data is assigned to another type of variable, an automatic type conversion
will take place if the following two conditions are met:
• The two types are compatible.
• The destination type is larger than the source type.
When these two conditions are met, a widening conversion takes place.
So the reason for it is,
For widening conversions, the numeric types, including integer and floating-point types,
are compatible with each other. However, there are no automatic conversions from the
numeric types to char or boolean.

The conversion from a byte to a char is a so-called Widening and Narrowing Primitive Conversion (JLS 5.1.4)
First, the byte is converted to an int via widening primitive conversion (§5.1.2), and then the resulting int is converted to a char by narrowing primitive conversion (§5.1.3).
The widening conversion from byte to int is fine (both are signed), but from int to char will loose both sign and (potentially) range (as char is 0 to 65536):
A narrowing primitive conversion may lose information about the overall magnitude of a numeric value and may also lose precision and range.
And
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
Because of this potential loss of precision, sign and informaiton you get a compilation error and an explicit cast is necessary to signal to the compiler that you know what you're doing.

Related

Casting problem regarding to compaund operators Java [duplicate]

byte a = 1;
byte b = 1;
byte c = a + b;
Throws error: possible loss of precision
byte subt = a_s - a_b;
^
required: byte
found: int
Is this behavior has something to do with jvm or its been defined in java language .
EDIT : And if it is defined in java language then does it because of keeping jvm in mind ?
Means if java supports byte datatype then why operation on byte results int
if java supports byte datatype then why operation on byte results int
Because that's how the Java Virtual Machine is designed. There is no instruction set to perform operation on a byte type. Rather the instruction set for int type is used for the operation on boolean, byte, char, and short types.
From JVM Spec - Section 2.11.1:
A compiler encodes loads of literal values of types byte and short using Java Virtual Machine instructions that sign-extend those values to values of type int at compile-time or run-time. Loads of literal values of types boolean and char are encoded using instructions that zero-extend the literal to a value of type int at compile-time or run-time. [..]. Thus, most operations on values of actual types boolean, byte, char, and short are correctly performed by instructions operating on values of computational type int.
The reason behind this is also specified in that section:
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. [...] Separate instructions can be used to convert between unsupported and supported data types as necessary.
For the details on what all instruction sets are available for various types, you can go through the table in that section.
There is also a table specifying the mapping of actual type to the JVM computational type:
JLS 5.6.2: Binary Numeric Promotion covers it:
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.
The compiler is doing the right thing. Because (a + b) can go beyond the maximum value that can be kept in a byte variable. If you tell the compiler a, b values don't change by using the 'final' keyword it wont complain anymore.
final byte a = 1;
final byte b = 1;
byte c = a + b;
Yes,It's language spec.
The addition(+) operator. while the adding, 'a' is converts(implicitly casts) to int type,
b as well to type int. Hence result is implicitly of type int.
Same for - operator too.
Compiler is right, declare variables to final or cast to byte:
byte b = 1;
byte c = 22;
byte a = (byte) (b + c);
JAVA : byte+byte = int
:)
While doing the arithmetic operations on any operands the result is stored in this form MAX(int,operand1 type,operand2 type,...operandN type)
Ex:
byte a=10;
byte b=20;
byte c=a+b;
then result of a+b will be stored in the form of MAX(int,operand1 type,operand2 type,...operandN type)
in this case
MAX(int,byte,byte) the max value is int which is maximum so c will have the int value but c has been declared as byte, and we can't store int(bigger) value into byte(smaller). the same applies for every arithmetic operator.
that is why the error says
error: incompatible types: possible lossy conversion from int to byte

Java: Type mismatch: cannot convert from int to char [duplicate]

If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").
byte a = 23;
byte b = 34;
byte c = a + b;
In this example, the compile error is on the third line.
Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.
To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.
byte a = 23;
byte b = 34;
byte c = (byte) (a + b);
Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)
Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.
The answer to your follow-up question is here:
operands of type byte and short are automatically promoted to int before being handed to the operators
So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".
I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.
Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).
So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.
But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.
The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:
a + b
where a and b are of type byte. This is shorthand for:
(int)a + (int)b
This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.
Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.
There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.
In Java Language Specification (5.6.2 Binary Numeric Promotion):
1 If any expression is of type double, then the promoted type is double, and other expressions that are not of type double undergo widening primitive conversion to double.
2 Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float.
3 Otherwise, if any expression is of type long, then the promoted type is long, and other expressions that are not of type long undergo widening primitive conversion to long.
4 Otherwise, none of the expressions are of type double, float, or long. In this case, the promoted type is int, and any expressions that are not of type int undergo widening primitive conversion to int.
Your code belongs to case 4. variables a and b are both converted to an int before being handed to the + operator. The result of + operation is also of type int not byte

narrow casting int to smaller types

If every operand in assignment and mathematical operations, before the expression performed, promote to int (if it doesn't have L, f, d flags);
And putting an int into a smaller primitive type (such as byte) should be done with narrow-casting;
So how the following assignment works?
byte a = 100;
If 100 is an integer, so putting it into a byte needs casting.
byte a = 100;
This works because...
If the right-hand side in an assignment context is a constant expression,
A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
Where
Literals of primitive type [...]
are a constant expression.
And the range of a byte is
[...] from -128 to 127, inclusive.
byte a = 100;
This works because byte range in java is from-128 to 127,so if you assign value upto 127,there is no need for cast.
Try to assign 128,you will get compiler error.
byte a = 128 ; //compiler error(incompatible type)
byte a = (byte)128;
It's a compile-time constant, and the compiler can determine that it'll fit in a byte. This actually did require a narrowing conversion in older versions of Java.

Purpose of char in java

I'm seeing both char and short are two bytes each,
also the following is valid:
char a = 'x';
int b = a;
long c = a;
However when I do short d = a; I'm getting an error that cannot convert from char to short.
even though both are two bytes.
One use of char I can see is when you print it, it displays the character. Is that the only use of char?
In Java the data type char is an unsigned 2 byte variable while a short is signed 2 byte variable. Because of this difference you cannot convert a char to a short because a char has that extra bit that isn't the signed bit.
This means that if you convert char to a short you would have to truncate the char which would cause the complaining.
You should probably want to read about data types and type casting to have a clear understanding.
When you tried to do short d=a; you are trying to do the 'Narrowing Primitive Conversion'.
5.1.3 Narrowing Primitive Conversions
The following 22 specific conversions
on primitive types are called the
narrowing primitive conversions:
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
Narrowing conversions may lose
information about the overall
magnitude of a numeric value and may
also lose precision.
While it is true that char is an unsigned 16-bit type, it is not designed to be used as such. Conceptually, char is a Unicode character (more precisely, a character from the Unicode subset that can be represented with 16 bits in UTF-16) which is something more abstract than just a number. You should only ever use chars for text characters. I think that making it an integer type is a kind of bad design on Java's side. It shouldn't have allowed any conversions between char and integer types except by using special utility methods. Like boolean is impossible to convert to integers and back.
char is generally only used for text, yes.
char is unsigned, while short is signed.
check out the Java Docs
it's all there... Char and Short aren't the same.
Normally, I use char for text, and short for numbers. (If I use short. I'd rather use int/long when they're available).
You may want to "cast" the variable. It's done like this:
char a = 'x';
short sVar = (short)a;
System.out.println(a);
System.out.println(sVar);
char is a Unicode-character and, therefore, must be unsigned. short is like all other numeric primitive types signed. Therefore, short and char cover two different ranges of values causing the compiler to complain about the assignment.

Java: why do I receive the error message "Type mismatch: cannot convert int to byte"

If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").
byte a = 23;
byte b = 34;
byte c = a + b;
In this example, the compile error is on the third line.
Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.
To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.
byte a = 23;
byte b = 34;
byte c = (byte) (a + b);
Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)
Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.
The answer to your follow-up question is here:
operands of type byte and short are automatically promoted to int before being handed to the operators
So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".
I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.
Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).
So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.
But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.
The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:
a + b
where a and b are of type byte. This is shorthand for:
(int)a + (int)b
This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.
Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.
There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.
In Java Language Specification (5.6.2 Binary Numeric Promotion):
1 If any expression is of type double, then the promoted type is double, and other expressions that are not of type double undergo widening primitive conversion to double.
2 Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float.
3 Otherwise, if any expression is of type long, then the promoted type is long, and other expressions that are not of type long undergo widening primitive conversion to long.
4 Otherwise, none of the expressions are of type double, float, or long. In this case, the promoted type is int, and any expressions that are not of type int undergo widening primitive conversion to int.
Your code belongs to case 4. variables a and b are both converted to an int before being handed to the + operator. The result of + operation is also of type int not byte

Categories

Resources