Explain how this Java program prints out 65535 - java

This is the class with the main method.
import java.util.*;
import java.io.*;
class Main {
public static void main(String args[])
System.out.println((int)(char)(byte)-1);
}
}
Please explain how this prints out the result "65535".

Let's follow it, according to the Java Language Specification:
-1
Integer Literals:
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).
So in hex that means:
0xFFFFFFFF {int -1}
(byte)0xFFFFFFFF
Narrowing Primitive Conversion (int to byte):
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.
0xFFFFFFFF {int -1} → 0xFF {byte -1}
(char)0xFF
Widening and Narrowing Primitive Conversion (byte to char):
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).
Widening Primitive Conversion (byte to int):
A widening conversion of a signed integer value to an integral type T simply sign-extends the two's-complement representation of the integer value to fill the wider format.
0xFF {byte -1} → 0xFFFFFFFF {int -1}
Narrowing Primitive Conversion (int to char):
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, [...]
0xFFFFFFFF {int -1} → 0xFFFF {char 65535}
(int)0xFFFF
Widening Primitive Conversion (char to int):
A widening conversion of a char to an integral type T zero-extends the representation of the char value to fill the wider format.
0xFFFF {char 65535} → 0x0000FFFF {int 65535}
Result: 65535

char is not signed. -1 (the integer negative one) becomes Character.MAX_VALUE (because of arithmetic underflow). It's equivalent to
System.out.println((int) Character.MAX_VALUE);
and thus you get (the perhaps surprising) 65535.

Related

Is Java char signed or unsigned for arithmetic?

Java char is a 16 bit data type, but is it signed or unsigned when it comes to performing arithmetic on it?
Can you use it as an unsigned 16 bit integer in arithmetic?
For example, is the following correct?
char c1;
char c2;
int i = c1 << 16 | c2;
Or is it necessary to strip the sign-extended bits off c2 first?
(I am sure the answer to this is elsewhere, but there doesn't seem to be picked up by obvious searches).
char is unsigned. From JLS§4.2.1:
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
...but note that when you use any of the various mathematic operations on them (including bitwise operations and shift operations), they're widened to another type based on the type of the other operand, and that other type may well be signed:
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.
For instance, char + char is int, so:
public class Example {
public static void main(String[] args) {
char a = 1;
char b = 2;
char c = a + b; // error: incompatible types: possible lossy conversion from int to char
System.out.println(c);
}
}
Re bit-extension, if we follow the link above to widening primitive conversion:
A widening conversion of a char to an integral type T zero-extends the representation of the char value to fill the wider format.
So char 0xFFFF becomes int 0x0000FFFF, not 0xFFFFFFFF.
From the specs
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
Since it's 16 bits, it means they are unsigned.

Error occured when assign int to char [duplicate]

You cannot convert from int to char, so this would be illegal
int i = 88; char c = i;,
However this is allowed char c = 88;.
Isn't a plain number and int literal? How is this allowed?
char is effectively an unsigned 16-bit integer type in Java.
Like other integer types, you can perform an assignment conversion from an integer constant to any integer type so long as it's in the appropriate range. That's why
byte b = 10;
works too.
From the JLS, section 5.2:
In addition, if the expression is a
constant expression (§15.28) of type
byte, short, char or int :
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.
A narrowing primitive
conversion followed by a boxing
conversion may be used if the type of
the variable is :
Byte and the value
of the constant expression is
representable in the type byte.
Short
and the value of the constant
expression is representable in the
type short.
Character and the value of
the constant expression is
representable in the type char.
Actually, converting from int to char is legal, it just requires an explicit cast because it can potentially lose data:
int i = 88;
char c = (char) i;
However, with the literal, the compiler knows whether it will fit into a char without losing data and only complains when you use a literal that is too big to fit into a char:
char c = 70000; // compiler error
Its because the literals for integer or smaller than int as byte ,short and char is int. Understand the following in this way.
code:
byte a = 10;//compile fine
byte b= 11;//compile fine
byte c = a+b;//compiler error[says that result of **a+b** is **int**]
the same happens for any mathematical operations as of 'Divide', 'multiply', and other arithmetic operation. so cast the result to get the literal in desired data type
byte c = (byte)(a+b);
So that the same reason why the value int need to have primitive cast to change the value in char.
Hope this make some sense.

Java char is also an int?

I was trying to get some code done for class:
public int getValue(char value) {
if (value == 'y') return this.y;
else if (value == 'x') return this.x;
Since I might not be able to return anything in the end, it told me to do this at the end:
return value;
This surprised me because the return type for the method was of type int. Yet, it was telling me to return a char! I'm using eclipse, and accustomed to the endless number of warnings and stuff, this was a major surprise.
So, is a char really an int? Why is this happening?
The Java Language Specification states
When a return statement with an Expression appears in a method
declaration, the Expression must be assignable (§5.2) to the declared
return type of the method, or a compile-time error occurs.
where the rules governing whether one value is assignable to another is defined as
Assignment contexts allow the use of one of the following:
a widening primitive conversion (§5.1.2)
and
19 specific conversions on primitive types are called the widening
primitive conversions:
char to int, long, float, or `double
and finally
A widening primitive conversion does not lose information about the
overall magnitude of a numeric value in the following cases, where the
numeric value is preserved exactly: [...]
A widening conversion of a char to an integral type T zero-extends the
representation of the char value to fill the wider format.
In short, a char value as the expression of a return statement is assignable to a return type of int through widening primitive conversion.
A char is smaller than an int, so you can return it and it will prepend zeroes to make a longer number. That's not the right thing to return - in your case I'd probably throw an exception instead; however, the editor suggested it because it's something that you're allowed to return and you need to return something.
The following code is legal:
char c = 'h';
int i = c;
In computing, everything is numbers! Just bits and bytes.
int, char, byte, short and long are just numbers. A char is just a number that the compiler knows is usually used for displaying the character represented by the particular number (e.g. 32 = space, 48 = zero, etc).
A String is a sequence of numbers and other stuff, so a bit more complicated. We don't want to go there.
An int is a four byte number and a char is a two byte number, so you can fit any char number in an int.
The designers of Java just decided they would let you convert from char to int without requiring any special casts or conversions.
A char is not an int. However, it is an integral type. That is to say, it's considered to be a whole number that can be converted to and from other integral types (long,short,byte and int), according to the Java Language Specification.
Basically what this means is that it is assignment-compatible to int. Its value is between 0 and 65535, and if you assign it to an int or cast it to an int and print it, you'll get the UTF-16 value of the character it represents.
By definition (in java) a char is an 8bit unsigned integer. (0 to 256)
An int an 32bit signed integer. (−2.147.483.648 to 2.147.483.647)
char a = 65; //65 is the ASCII Number of 'A'
System.out.println(a);
>>> A
b = a + 1
System.out.println(b);
>>> B
java autoboxing converts char to int and vice versa
There is an implicit and natural conversion from int to char and vice-versa. Note that you thus have the usual arithmetic defined on charm which comes very handy when you want, let's say, to iterate on the alphabet :
for (char c='a' ; c<='z' ; c++) { ... }
However, note that a char is 2 bytes long whereas an int is 4 bytes long, so casting an int down to a char may result in an integer overflow.
Hope this little example solves your confusion:
public int getValue(int value) {
if (value == 'y')
return this.y;
else if (value == 'x')
return this.x;
}
If you pass char as an int like getValue('x'), it would return the value of the int.

confusing in type conversion and giving unexpected result

public class Multicast {
public static void main(String[] args) {
System.out.println((int) (char) (byte) -2);
}
}
I am confuse about the type conversion and also giving unexpected result (it prints 65534, not -2 as expected).
The confusing result is due to the fact that char is an unsigned type. When -2 is converted to char, its bit representation becomes 1111111111111110 in binary, because two's complement representation is used. That representation becomes a positive 65534 when converted to decimal - the result you see printed by your program.
In Java, char is an unsigned type (and byte is a signed type). So (char)-2 is 65534. Then you widen that to be an int.
your confusion on the results of your code is partly due to sign-extension. I'll try to add a more detailed explanation that may help with your confusion.
char a = '\uffff';
byte b = (byte)a; // b = 0xFF
this DOES result in the loss of information. This is considered a narrowing conversion. Converting a char to a byte "simply discards all but the n lowest order bits".
The result is: 0xFFFF -> 0xFF
char c = (char)b; // c = 0xFFFF
Converting a byte to a char is considered a special conversion. It actually performs TWO conversions. First, the byte is SIGN-extended (the new high order bits are copied from the old sign bit) to an int (a normal widening conversion). Second, the int is converted to a char with a narrowing conversion.
The result is: 0xFF -> 0xFFFFFFFF -> 0xFFFF
int d = (int)c; // d = 0x0000FFFF
Converting a char to an int is considered a widening conversion. When a char type is widened to an integral type, it is ZERO-extended (the new high order bits are set to 0).
The result is: 0xFFFF -> 0x0000FFFF. When printed, this will give you 65535.

char and int in Java

I was surprised to see this code work. I thought that char and int were two distinct data types in Java and that I would have had to cast the char to an int for this to give the ascii equivelent. Why does this work?
String s = "hello";
int x = s.charAt(1);
System.out.println(x);
A char can be automatically converted to an int. See JLS 5.1.2:
The following 19 specific conversions on primitive types are called the widening primitive conversions:
...
char to int, long, float, or double
...
A widening conversion of a signed integer value to an integral type T simply sign-extends the two's-complement representation of the integer value to fill the wider format. A widening conversion of a char to an integral type T zero-extends the representation of the char value to fill the wider format.
(emphasis added)
char and int are two distinct types, but this works because an int has more precision than a char. That is, every value of char can be represented as an int so no data is lost in the cast.

Categories

Resources