So I came across something that confused me when casting a byte to char, usually I would do this:
for (byte b:"ABCDE".getBytes()) {
System.out.println((char)b);
}
Which will print out
A
B
C
D
E
I accidentally left a + between the (char) and b and got the same result!?
Like so:
for (byte b:"ABCDE".getBytes()) {
System.out.println((char) + b);
}
Why exactly is this happening?
Am I essentially doing (char)(0x00 + b)? Because
System.out.println((char) - b);
yields a different result.
Note: Using Java version 1.8.0_20
Why exactly is this happening?
If you put a unary - operator before a number or expression it negates it.
Similarly, if you put a unary + operator before a number or expression it does nothing.
A safer way to convert a byte to a char is
char ch = (char)(b & 0xFF);
This will work for characters between 0 and 255, rather than 0 to 127.
BTW you can use unary operators to write some confusing code like
int i = (int) + (long) - (char) + (byte) 1; // i = -1;
b is a byte, and that be expressed as + b as well. For example, 3 can be written as +3 as well. So, ((char) + b) is same as ((char) b)
The + is the unary plus operator - like you can say that 1 is equivalent to +1, b is equivalent to +b. The space between + and b is inconsequential. This operator has a higher precedence than the cast, so after it's applied (doing nothing, as noted), the resulting byte is then cast to a char and produces the same result as before.
Related
When adding 'a' + 'b' it produces 195. Is the output datatype char or int?
The result of adding Java chars, shorts, or bytes is an int:
Java Language Specification on Binary Numeric Promotion:
If any of the operands is of a reference type, unboxing conversion
(§5.1.8) is performed. Then:
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.
But note what it says about compound assignment operators (like +=):
The result of the binary operation is converted to the type of the left-hand variable ... and the result of the conversion is stored into the variable.
For example:
char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK
One way you can find out the type of the result, in general, is to cast it to an Object and ask it what class it is:
System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer
If you're interested in performance, note that the Java bytecode doesn't even have dedicated instructions for arithmetic with the smaller data types. For example, for adding, there are instructions iadd (for ints), ladd (for longs), fadd (for floats), dadd (for doubles), and that's it. To simulate x += y with the smaller types, the compiler will use iadd and then zero the upper bytes of the int using an instruction like i2c ("int to char"). If the native CPU has dedicated instructions for 1-byte or 2-byte data, it's up to the Java virtual machine to optimize for that at run time.
If you want to concatenate characters as a String rather than interpreting them as a numeric type, there are lots of ways to do that. The easiest is adding an empty String to the expression, because adding a char and a String results in a String. All of these expressions result in the String "ab":
'a' + "" + 'b'
"" + 'a' + 'b' (this works because "" + 'a' is evaluated first; if the "" were at the end instead you would get "195")
new String(new char[] { 'a', 'b' })
new StringBuilder().append('a').append('b').toString()
String.format("%c%c", 'a', 'b')
Binary arithmetic operations on char and byte (and short) promote to int -- JLS 5.6.2.
You may wish to learn the following expressions about char.
char c='A';
int i=c+1;
System.out.println("i = "+i);
This is perfectly valid in Java and returns 66, the corresponding value of the character (Unicode) of c+1.
String temp="";
temp+=c;
System.out.println("temp = "+temp);
This is too valid in Java and the String type variable temp automatically accepts c of type char and produces temp=A on the console.
All the following statements are also valid in Java!
Integer intType=new Integer(c);
System.out.println("intType = "+intType);
Double doubleType=new Double(c);
System.out.println("doubleType = "+doubleType);
Float floatType=new Float(c);
System.out.println("floatType = "+floatType);
BigDecimal decimalType=new BigDecimal(c);
System.out.println("decimalType = "+decimalType);
Long longType=new Long(c);
System.out.println("longType = "+longType);
Although c is a type of char, it can be supplied with no error in the respective constructors and all of the above statements are treated as valid statements. They produce the following outputs respectively.
intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65
char is a primitive numeric integral type and as such is subject to all the rules of these beasts including conversions and promotions. You'll want to read up on this, and the JLS is one of the best sources for this: Conversions and Promotions. In particular, read the short bit on "5.1.2 Widening Primitive Conversion".
The Java compiler can interpret it as either one.
Check it by writing a program and looking for compiler errors:
public static void main(String[] args) {
int result1 = 'a' + 'b';
char result2 = 'a' + 'b';
}
If it's a char, then the first line will give me an error and the second one will not.
If it's an int, then the opposite will happen.
I compiled it and I got..... NO ERRORS. So Java accepts both.
However, when I printed them, I got:
int: 195
char: Ã
What happens is that when you do:
char result2 = 'a' + 'b'
an implicit conversion is performed (a "primitive narrowing conversion" from int to char).
According to the binary promotion rules, if neither of the operands is double, float or long, both are promoted to int. However, I strongly advice against treating char type as numeric, that kind of defeats its purpose.
While you have the correct answer already (referenced in the JLS), here's a bit of code to verify that you get an int when adding two chars.
public class CharAdditionTest
{
public static void main(String args[])
{
char a = 'a';
char b = 'b';
Object obj = a + b;
System.out.println(obj.getClass().getName());
}
}
The output is
java.lang.Integer
char is represented as Unicode values and where Unicode values are represented by \u followed by Hexadecimal values.
As any arithmetic operation on char values promoted to int , so the result of 'a' + 'b' is calculated as
1.) Apply the Unicode values on corresponding char using Unicode Table
2.) Apply the Hexadecimal to Decimal conversion and then perform the operation on Decimal values.
char Unicode Decimal
a 0061 97
b 0062 98 +
195
Unicode To Decimal Converter
Example
0061
(0*163) + (0*162) + (6*161) +
(1*160)
(0*4096) + (0*256) + (6*16) + (1*1)
0 + 0 + 96 + 1 = 97
0062
(0*163) + (0*162) + (6*161) +
(2*160)
(0*4096) + (0*256) + (6*16) + (2*1)
0 + 0 + 96 + 2 = 98
Hence 97 + 98 = 195
Example 2
char Unicode Decimal
Ջ 054b 1355
À 00c0 192
--------
1547 +
1163 -
7 /
260160 *
11 %
While Boann's answer is correct, there is a complication that applies to the case of constant expressions when they appear in assignment contexts.
Consider the following examples:
char x = 'a' + 'b'; // OK
char y = 'a';
char z = y + 'b'; // Compilation error
What is going on? They mean the same thing don't they? And why is it legal to assign an int to a char in the first example?
When a constant expression appears in an assignment context, the Java compiler computes the value of the expression and sees if it is in the range of the type that you are assigning to. If it is, then an implicit narrowing primitive conversion is applied.
In the first example, 'a' + 'b' is a constant expression, and its
value will fit in a char, so the compiler allows the implicit narrowing of the int expression result to a char.
In the second example, y is a variable so y + 'b' is NOT a
constant expression. So even though Blind Freddy can see that the
value will fit, the compiler does NOT allow any implicit narrowing, and you get a compilation error saying that an int cannot be assigned to a char.
There are some other caveats on when an implicit narrowing primitive conversion is allowed in this context; see JLS 5.2 and JLS 15.28 for the full details.
The latter explains in detail the requirements for a constant expression. It may not be what you may think. (For example, just declaring y as final doesn't help.)
How would one concatenate two byte primitives to get one char in java? I'm currently trying this:
byte a = 0x01;
byte b = 0x02;
char c = (char) (a + b);
which gives 0x03. The answer I want is 0x0102.
Is there no simple way to concatenate primitives? I'm surprised there isn't an obvious solution, since it seems like it should be easy. Maybe there is and I just don't see it. :p
Any help would be appreciated.
Thanks!
By shifting left 8 bits and adding. Something like,
byte a = 0x01;
byte b = 0x02;
char c = (char) ((a << 8) + b);
System.out.println(Integer.toHexString(c));
Output is
102
As pointed out in the comments (by #ChrisMartin) you could bitwise-or (and I'll add you might also xor) like
char c = (char) ((a << 8) | b);
and
char c = (char) ((a << 8) ^ b);
To all achieve the same result. Since you should Write Dumb Code I suggest you use whichever you find easiest to understand.
If you are not opposed to using a 3rd party library, Guava's Chars.fromBytes method does exactly this:
char c = Chars.fromBytes(0x01, 0x02);
The correct expression is ((a << 8) | (b & 0xff)):
byte a = (byte) 0x81;
byte b = (byte) 0x82;
char c = (char) ((a << 8) | (b & 0xff));
A byte, when used in an expression, is promoted to an int and when this is done, it is sign-extended. The expressions in the other answer only worked when b <= 127.
If you add 1 more to that value, as a byte, it will have the value -128. (The range of a byte in Java is -128 to 127) so you usually have to mask a byte with b & 0xff when you're using it to store unsigned numbers. You don't need to do that with a in the above expression since all the high-order bits are shifted out of the resulting 16-bit char.
When adding 'a' + 'b' it produces 195. Is the output datatype char or int?
The result of adding Java chars, shorts, or bytes is an int:
Java Language Specification on Binary Numeric Promotion:
If any of the operands is of a reference type, unboxing conversion
(§5.1.8) is performed. Then:
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.
But note what it says about compound assignment operators (like +=):
The result of the binary operation is converted to the type of the left-hand variable ... and the result of the conversion is stored into the variable.
For example:
char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK
One way you can find out the type of the result, in general, is to cast it to an Object and ask it what class it is:
System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer
If you're interested in performance, note that the Java bytecode doesn't even have dedicated instructions for arithmetic with the smaller data types. For example, for adding, there are instructions iadd (for ints), ladd (for longs), fadd (for floats), dadd (for doubles), and that's it. To simulate x += y with the smaller types, the compiler will use iadd and then zero the upper bytes of the int using an instruction like i2c ("int to char"). If the native CPU has dedicated instructions for 1-byte or 2-byte data, it's up to the Java virtual machine to optimize for that at run time.
If you want to concatenate characters as a String rather than interpreting them as a numeric type, there are lots of ways to do that. The easiest is adding an empty String to the expression, because adding a char and a String results in a String. All of these expressions result in the String "ab":
'a' + "" + 'b'
"" + 'a' + 'b' (this works because "" + 'a' is evaluated first; if the "" were at the end instead you would get "195")
new String(new char[] { 'a', 'b' })
new StringBuilder().append('a').append('b').toString()
String.format("%c%c", 'a', 'b')
Binary arithmetic operations on char and byte (and short) promote to int -- JLS 5.6.2.
You may wish to learn the following expressions about char.
char c='A';
int i=c+1;
System.out.println("i = "+i);
This is perfectly valid in Java and returns 66, the corresponding value of the character (Unicode) of c+1.
String temp="";
temp+=c;
System.out.println("temp = "+temp);
This is too valid in Java and the String type variable temp automatically accepts c of type char and produces temp=A on the console.
All the following statements are also valid in Java!
Integer intType=new Integer(c);
System.out.println("intType = "+intType);
Double doubleType=new Double(c);
System.out.println("doubleType = "+doubleType);
Float floatType=new Float(c);
System.out.println("floatType = "+floatType);
BigDecimal decimalType=new BigDecimal(c);
System.out.println("decimalType = "+decimalType);
Long longType=new Long(c);
System.out.println("longType = "+longType);
Although c is a type of char, it can be supplied with no error in the respective constructors and all of the above statements are treated as valid statements. They produce the following outputs respectively.
intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65
char is a primitive numeric integral type and as such is subject to all the rules of these beasts including conversions and promotions. You'll want to read up on this, and the JLS is one of the best sources for this: Conversions and Promotions. In particular, read the short bit on "5.1.2 Widening Primitive Conversion".
The Java compiler can interpret it as either one.
Check it by writing a program and looking for compiler errors:
public static void main(String[] args) {
int result1 = 'a' + 'b';
char result2 = 'a' + 'b';
}
If it's a char, then the first line will give me an error and the second one will not.
If it's an int, then the opposite will happen.
I compiled it and I got..... NO ERRORS. So Java accepts both.
However, when I printed them, I got:
int: 195
char: Ã
What happens is that when you do:
char result2 = 'a' + 'b'
an implicit conversion is performed (a "primitive narrowing conversion" from int to char).
According to the binary promotion rules, if neither of the operands is double, float or long, both are promoted to int. However, I strongly advice against treating char type as numeric, that kind of defeats its purpose.
While you have the correct answer already (referenced in the JLS), here's a bit of code to verify that you get an int when adding two chars.
public class CharAdditionTest
{
public static void main(String args[])
{
char a = 'a';
char b = 'b';
Object obj = a + b;
System.out.println(obj.getClass().getName());
}
}
The output is
java.lang.Integer
char is represented as Unicode values and where Unicode values are represented by \u followed by Hexadecimal values.
As any arithmetic operation on char values promoted to int , so the result of 'a' + 'b' is calculated as
1.) Apply the Unicode values on corresponding char using Unicode Table
2.) Apply the Hexadecimal to Decimal conversion and then perform the operation on Decimal values.
char Unicode Decimal
a 0061 97
b 0062 98 +
195
Unicode To Decimal Converter
Example
0061
(0*163) + (0*162) + (6*161) +
(1*160)
(0*4096) + (0*256) + (6*16) + (1*1)
0 + 0 + 96 + 1 = 97
0062
(0*163) + (0*162) + (6*161) +
(2*160)
(0*4096) + (0*256) + (6*16) + (2*1)
0 + 0 + 96 + 2 = 98
Hence 97 + 98 = 195
Example 2
char Unicode Decimal
Ջ 054b 1355
À 00c0 192
--------
1547 +
1163 -
7 /
260160 *
11 %
While Boann's answer is correct, there is a complication that applies to the case of constant expressions when they appear in assignment contexts.
Consider the following examples:
char x = 'a' + 'b'; // OK
char y = 'a';
char z = y + 'b'; // Compilation error
What is going on? They mean the same thing don't they? And why is it legal to assign an int to a char in the first example?
When a constant expression appears in an assignment context, the Java compiler computes the value of the expression and sees if it is in the range of the type that you are assigning to. If it is, then an implicit narrowing primitive conversion is applied.
In the first example, 'a' + 'b' is a constant expression, and its
value will fit in a char, so the compiler allows the implicit narrowing of the int expression result to a char.
In the second example, y is a variable so y + 'b' is NOT a
constant expression. So even though Blind Freddy can see that the
value will fit, the compiler does NOT allow any implicit narrowing, and you get a compilation error saying that an int cannot be assigned to a char.
There are some other caveats on when an implicit narrowing primitive conversion is allowed in this context; see JLS 5.2 and JLS 15.28 for the full details.
The latter explains in detail the requirements for a constant expression. It may not be what you may think. (For example, just declaring y as final doesn't help.)
What is the difference between += and =+?
Specifically, in java, but in general also.
i += 4;
means
i = i + 4; // increase i by 4.
While
i =+ 4;
is equivalent to
i = +4; // assign 4 to i. the unary plus is effectively no-op.
(See http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.3 for what a unary + does.)
+= is an operator that increments the left-hand side of the assignment by the value of the right-hand side and assigns it back to the variable on the left-hand side. =+ is not an operator but, in fact, two operators: the assignment operator = and the unary plus + (positive) operator which denotes the value on the right-hand side is positive. It's actually redundant because values are positive unless they are negated with unary minus. You should avoid the =+ construct as it's more likely to cause confusion than do any actual good.
+= is get and increment:
a += 5; // adds 5 to the value of a
=+ isn't really a valid identifier on its own, but might show up when you're using the unary + operator:
a =+ 5; // assigns positive five to a
=+ is not an operator. The + is part of the number following the assignment operator.
int a = 4;
int b = 4;
a += 1;
b =+1;
System.out.println("a=" + a + ", b=" + b);
This shows how important it is to properly format your code to show intent.
+= is a way to increment numbers or String in java. E.g.
int i = 17;
i += 10; // i becomes 27 now.
There is no =+ operator. But if you do i =+ 10; it means i is equal to +10 which is equal to just 10.
Specifically, in java, but in general also.
In Java x += <expr>; is equivalent to x = x + ( <expr> ); where the + operator may be the arithmetical add operator or the string concatenation operator, depending on the type of x. On the other hand, x =+ <expr>; is really an ugly way of writing x = + <expr>; where the + is unary plus operator ... i.e. a no-op for numeric types and a compilation error otherwise.
The question is not answerable in the general case. Some languages support a "+=" operator, and others don't. Similarly, some languages might support a "=+" operator and others won't. And some languages may allow an application to "overload" one or other of the operators. It simply makes no sense to ask what an operator means "in general".
I don't know what you mean by "in general", but in the early versions of C language (which is where most of Java syntax came from, through C++), =+ was the original syntax for what later became +=, i.e. i =+ 4 was equivalent to i = i + 4.
CRM (C Reference Manual) is the document the describes C language with =+, =-, =>> and so on.
When you have a+=b, that means you're adding b to whatever's already in a. If you're doing a=+b, however, you're assigning +b to a.
int a=2;
int b=5;
a+=b;
System.out.println(a); //Prints 7
a=2;
b=5;
a=+b;
System.out.println(a); //Prints 5
The += operation as you said, is used for increment by a specific value stated in the R value.Like,
i = i+1;
//is equivalent to
i += 1;
Whereas, =+ is not any proper operation, its basically 2 different operators equal and unary plus operators written with each other.Infact the + sign after = makes no sense, so try not to use it.It will only result in a hocum.
i =+ 1;
//is equivalent to
i = +(1);
Can somebody explain me why the following piece of code fails to compile. The error is: "Possible loss of precision." :
byte a = 50;
byte b = 40;
byte sum = (byte)a + b;
System.out.println(sum);
Thank you.
Note that the cast has a higher precedence than the + operator. Your code does this:
byte a = 50;
byte b = 40;
byte sum = ((byte)a) + b;
System.out.println(sum);
The cast is redundant, since a is already a byte. You probably meant this:
byte a = 50;
byte b = 40;
byte sum = (byte) (a + b);
System.out.println(sum);
Because the two byte variables are operands to +, they are implicitly promoted to int. This is called Numeric Promotion. Because int is larger than byte, and the result of a + b yields int, casting to byte possibly chops off some bits, as int is larger than byte. Hence the "loss of precision"
Doc for implicit numeric promotion:
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#170983
Doc for the size of types:
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html
You did right by identifying that a cast is required, but unfortunately you did not apply it to the right expression due to precedence of operators.
Consider the following snippet:
static void f(char ch) {
System.out.println("f(char)");
}
static void f(int i) {
System.out.println("f(int)");
}
public static void main(String[] args) {
char ch = 'X';
f( (char) ch + 1 ); // prints "f(int)"
f( (char) (ch + 1) ); // prints "f(char)"
}
The cast has a higher precedence than the addition, which is why the snippet prints what it does. That is, the first call is equivalent to f( ((char) ch) + 1 );. The result of the addition is an int, which is why the f(int) overload is invoked.
The lesson here is that you should always use parenthesis unless you're doing a very simple cast. In general, always consider using parentheses to make the order of evaluation explicit, even if they're not necessary. They lead to a better, more readable code.
Bytes are added using "int" arithmetic; thus the result is an int and must be cast back from int to byte, which leads to the possibility of truncation.