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.
Related
This question already has answers here:
Why is casting to short to char is a narrowing conversion?
(2 answers)
Java - why does char get implicitly cast to byte (and short) primitive, when it shouldn't?
(5 answers)
Conversion between character and int in Java
(3 answers)
Closed 5 years ago.
I have the following method in Java:
private static short charToShort_1() {
return 's';
}
private static char shortToChar_1() {
return ((short) 15);
}
private static short charToShort_2() {
char ch = 's';
return ch;
}
private static char shortToChar_2() {
short number = 15;
return number;
}
Why "charToShort_1" and "shortToChar_1" are compiled successfully?
In the same time the last two methods "charToShort_2" and "shortToChar_2" can not be compiled (because explicit cast is necessary).
Here :
private static short charToShort_1() {
return 's';
}
's' is a constant expression and this value is representable in short.
So the compiler does an implicit conversion.
The JLS states :
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.
The short values range is -32,768 to 32,767 (inclusive).
So a constant expression char out of these bounds will produce a compilation error :
private static short charToShort_2() {
return '耀'; // 32768 numeric value
}
About this method that doesn't compile :
private static short charToShort_2() {
char ch = 's';
return ch;
}
char ch = 's'; is not a constant expression.
You may reassign ch with a new char value that is not representable in short (such as '耀' that is represented by the 32768 numeric value).
So the compiler expects you explicitly cast it to short as the conversion
may be a narrowing primitive conversion.
Change it into a final variable and you will see that it compiles fine :
private static short charToShort_2() {
final char ch = 's';
return ch;
}
About this method that casts from short to char, the compilation error reason is exactly the same as for charToShort_2()
At last, about shortToChar_1() :
private static char shortToChar_1() {
return ((short) 15);
}
The cast to short may give the impression that you spend less memory than if you had used a int:
private static char shortToChar_1() {
return 15;
}
In fact, it doesn't change anything as in both cases the compiler will use the bipush JVM instruction to push a byte onto the stack as an integer value.
The real answer lies in this statement from §5.2 of the Java Language Specification (for Java 8, but applies to previous versions as well)
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.
So constant expressions are treated specially in that they allow some narrowing conversions that are disallowed for other expressions.
3 and 4 method are wrong because this transformation is narrowing (with loss of data). You must explicitly indicate that you understand and agree with all the risks associated with this transformation.
5.1.3 paragraph
https://docs.oracle.com/javase/specs/jls/se6/html/conversions.html
The answer is pretty sinple because char is the unsigned data type in java whereas short is signed data type,so there is no implicit conversion for it in java
according to the Oracle
char to short is a narrowing primitive conversion
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.
Can someone explain to me why the following code compiles OK in Java?
char c = 'a' + 10;
Why is this not equivalent to the following, which does not compile?
int i = 10;
char c = 'a' + i;
The Java Language Specification (section 3.10.1) states "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)." Section 4.2.2 refers to "The numerical operators, which result in a value of type int or long." So the result of the addition should, in my understanding, be an int, which cannot be assigned to the char variable c.
However, it compiles fine (at least in Sun JDK 1.6.0 release 17 and in Eclipse Helios).
Rather an artificial example perhaps, but it is used in an introductory Java course I have been teaching, and it now occurs to me that I don't really understand why it works.
It is because the compiler can check that it ('a' + 10) is within the bounds of a char whereas it cannot (in general) check that 'a' + <an integer> is within the bounds.
'a' + 10 is a compile-time constant expression with the value of 'k', which can initialise a variable of type char. This is the same as being able to assign a byte variable with a literal integer in [-128, 127]. A byte in the range of [128, 255] may be more annoying.
char is actually an unsigned 16-bit integer with a range 0-65535. So you can assign any integer literal in that range to a char, e.g., "char c = 96", which results in "c" holding the character "a". You can print out the result using System.out.println(c).
For the constant expression on the right-hand-side of "char c = 'a' + 10", 'a' is promoted to int first because of the Java numeric promotion rules and the integer value is 96. After adding 10 to it, we get a literal integer 106, which can be assigned to a char.
The right-hand-side of "char c = 'a' + i" is not a constant expression and the expression result assignment rule requires an explicit cast from int to char, i.e., "char c = (char) ('a' + i)".
This code should works:
int i = 10;
char x = (char)('a' + i);
The constant is of a different type (I know the spec says that 10 should be an int, but the compiler doesn't see it that way).
In char c = 'a' + 10, 10 is actually considered a constant variable of type char (so it can be added to a). Therefore char c = char + char works.
In int i = 10;
char c = 'a' + i; You are adding a char to an integer (an integer can be much bigger than a char, so it chooses the bigger data type [int] to be the result a.k.a: 'a' + i = int + int). So the result of the addition is an integer, which cannot fit into the char c.
If you explicitly casted i to be a char (e.g.: char c = 'a' + (char)i;) it could work or if you did the opposite (e.g.: int c = (int)'a' + i;) it would work.
According to Java specification as of 2020 for widening and narrowing conversions of integral values in expressions:
"In a numeric arithmetic context ... the promoted type is int,
and any expressions that are not of type int undergo widening
primitive conversion to int"
In assignment context:
"...if the expression is a constant expression of type byte, short,
char, or int:
• A narrowing primitive conversion may be used if the
variable is of type byte, short, or char, and the value of the
constant expression is representable in the type of the variable."
So, in char c = 'a' + 10; the left constant value is a charand the right constant value is int fitting into a char. While there is an assignment and int 10 fits into char, int gets converted to char. And the overall result of addition is char.
And in char c = 'a' + i; (where int i = 10;) the i is not constant, so, notwithstanding the assignment, the char 'a' is promoted to int and the overall result is int. Thus, the assignment is erroneous without an explicit typecast.
Note, that the following original answer is wrong (it cites treatment in numeric choice contexts, like in switch statement):
According to Java specification for widening and narrowing conversions in expressions:
If any expression is of type int and is not a constant expression,
then the promoted type is int, and other expressions that are not of
type int undergo widening primitive conversion to int.
...
if any expression is of type char, and every other expression is
either of type 'char' or a constant expression of type 'int' with a
value that is representable in the type 'char', then the promoted type
is char, and the int expressions undergo narrowing primitive
conversion to char.
So, in char c = 'a' + 10; the left expression is a char and the right constant expression is int fitting into a char. So, the constant gets converted to char. And the overall result is char.
And in char c = 'a' + i; (where int i = 10;) the right expression is not constant, so the the char 'a' is promoted to int and the overall result is int.
This question already has answers here:
Converting Chars to Ints in Java
(2 answers)
Closed 8 years ago.
Here is my code but I am not getting how int getValue() method accepting char type as return value. How is it working? could any body please explain me how this method is working?
public class CharToInteger {
private static Scanner input;
public static int getValue(char character){
return character;
}
public static void main(String[] args) {
input = new Scanner(System.in);
System.out.println("Enter a character to get value of it:");
String inputString=(String) input.next();
char inputCharacter=inputString.charAt(0);
System.out.println(getValue(inputCharacter));
}
}
Thanks in advance :)
public static int getValue(char character){
return character;//<-- unicode value is being returned, e.g. char 0 -> int 48
// char ranges from 0 - 65535
}
From JSL:
5.1.4. Widening and Narrowing Primitive Conversion
The following conversion combines both widening and narrowing
primitive conversions:
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).
see more:
OK, so first things first:
This is a widening primitive type conversion, so this is legal. You can:
int foo() { return 'a' /* character constant */ };
long foo() { return 3; /* int constant */ }
But you CANNOT DO:
char foo() { return 1; /* int constant */ }
int foo() { return 1L; /* long constant */ }
Second: what it returns is NOT THE ASCII CODE AT ALL. Java does Unicode.
It just happens that when Java was created, Unicode only defined code points fitting 16 bits; hence char was created as a 2 byte, unsigned primitive type (it is the only unsigned primitive type in Java) matching the then-called UCS-2 character coding (a 1 to 1 mapping between the coding and code points).
However, afterwards Unicode went "wide" and code points outside the BMP (ie, greater than U+FFFF) appeared; since then UCS-2 became UTF-16, and code points outside the BMP require two chars for one code point (a leading surrogate and a trailing surrogate; in previous Unicode versions, and in the Java API, those were called resp. high and low surrogate). A char is therefore now a UTF-16 code unit.
It is still true, however, that for code points in the BMP, the char value exactly matches the code point.
Now, in order to "fix" your program to accurately display the "character value", ie the code point, for each possible entry, you would do that (Java 8):
public static void main(String[] args) {
final Scanner input = new Scanner(System.in);
System.out.println("Enter a character to get value of it:");
String inputString = input.next();
// Print -1 on an empty input
final OptionalInt codepoint = inputString.codePoints().findFirst();
System.out.println(codepoint.isPresent() ? codepoint.get() : -1);
}
This will also handle code points outside the BMP.
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.
And it is legal to ,
public static int getValue(char character){
return character;
}
This is because char in java is 2 bytes and int is 4 bytes. So it is a widening conversion, which happens implicitly in Java. The return value is the ASCII value on the input character.
Char is UTF-16 code representation - read it as 2-byte integral value. int is 4-byte integral value. Java can implicitly cast smaller sized integrals to larger ones - char to int, int to long, because conversion this way doesn't lead to precision or data loss.
The vice versa way doesn't work - you cannot implicitly convert int to char and long to int, because int has a much wider range of possible values than char.
Put simply, Java is willing to implicitly convert a char to an int.
It will convert it to a 16-bit Unicode value.
If the input were 'A' you will get '65' as your output.
It's arguable (by me!) that characters and integers are sufficiently different that the language shouldn't be so sloppy as from time to time it can lead to surprise behaviour.
If you want chapter and verse look at Sec 5.1.2 here:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html
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.