Char array compile time error upon assign a value from array - java

So I have this code
char [] a = {'a','b','c'};
char c = 'a' + 'b'; //works
char c2 = 98 + 97; //works
char c3 = a[0] + a[1]; //compile time error
So all of them are the same functionality but upon getting and using an array value it is giving me a compile time error. What is the cause of this??
The result of the additive operator applied two char operands is an int.
then why can I do this?
char c2 = (int)((int)98 + (int)97);

The result of the additive operator applied two char operands is an int.
Binary numeric promotion is performed on the operands.
The type of an additive expression on numeric operands is the promoted type of its operands
The first two are constant expressions where the resulting value is an int that can be safely assigned to a char.
The third is not a constant expression and so no guarantees can be made by the compiler.
Similarly
then why can I do this?
char c2 = (int)((int)98 + (int)97);
That is also a constant expression and the result can fit in a char.
Try it with bigger values, 12345 and 55555.

Related

Adding Byte and Short [duplicate]

The rules for promotion is "when operands are of different types, automatic binary numeric promotion occurs with the smaller operand type being converted to the larger". But the operands are of same type for example,
byte=byte+byte // Compile time error... found int..
So why is it so?
There's no + operator for byte. Instead, both operands are promoted to int, so you've got
byte = byte + byte
... becomes (widening to find + operator) ...
byte = int + int
... becomes (result of + operator) ...
byte = int
... which then fails because there's no implicit conversion from int to byte. You need to cast:
byte a = 1;
byte b = 2;
byte c = (byte) (a + b);
Here are the actual rules for numeric promotion, from section 5.6.2 of the JLS:
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:
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.
You were provided with correct answer about automatic promotion to 'int'.
There is one more note about that - compound assignment operators behave as they have an implicit type case. Example:
byte b1 = 1;
byte b2 = 2;
b1 = b1 + b2; // compilation fails
b1 += b2; // compilation successful
I would like to talk about Promotion in general
Java can evaluate only arithmetic expressions in which the operands’ types are identical
For example, in an expression containing int and double values, the int values are promoted to double values for use in the expression.
in another word
double someVar = 1 / 2;// someVar = 0
but
double someVar = (double)1 / 2;// someVar = 0.5
why?
we use the (double) cast operator to create a temporary
floating-point copy of its operand "1" (it's called explicit conversion)
The calculation now consists of a floating-point value (the temporary double copy of 1) divided by the integer 2
according to the above statement, Java performs an operation called promotion (or implicit conversion), so the int values are promoted to double values for use in the expression => the integer 2 is promoted to double
the expression became double someVar = 1.0 / 2.0; // someVar= 0.5
hope this is helpful, even if it is out of the core of the question
To understand this you should refer the 2 things:
Implicit Casting:
byte (8 bit) -> short (16 bit) -> int (32 bit) -> float (32 bit) -> double (64 bit)
char (16 bit) -> int (32 bit)
Arithmetic Operator Rules
Operator Precedence Rule : This rule states that Group of (*,/, %) will be evaluated first. Then Group of (+,-) operator will be evaluated. From a same Group of Operators, calculate from the left.
Operand Promotion Rule : This rule states that Operands having data type smaller than int will be promoted to int. order of promotion (byte->short->int, char->int)
Same Type Operand Rule: This rule states that if both operands are int,long,float,double then the same type is carried to the result type.
i.e. long+long => long , float + float => float, int+int => int
Mix Type Operand Rule : Follow the order of Promotion (int->long->float->double) if any of the operand is from the above order then the smaller will be promoted to the bigger one and result will be calculated in bigger type.
i.e. long + double => double , int + long => long
From this SO question, and above answers due to + arithmetic operator, both operands are converted to type int.
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2; // compile time error
In above code, value of b1 and b2 will be resolved at runtime, so compiler will convert both to int before resolving the value.
But if we consider the following code,
final byte b1 = 1;
final byte b2 = 2;
int b3 = b1 + b2; // constant expression, value resolved at compile time
b1 and b2 are final variables and values will be resolved at compile time so compilation won't fail.

What is the return type of Java built-in array's access operator when contains primitive type?

When array xs has primitive char values and someone try to accessing that value using [], what is the return type?
Is it primitive char or wrapper Character?
I think it's always Character type, when array contains either char or Character.
Because when char minus int, the type of result is char.
char x = 'A' - 1;
When Character minus int, the type of result is int.
int x = new Character('A') - 1;
And result type of expression xs[0] - 1 is always int.
char[] xs = {'A'};
int x = xs[0] - 1;
char[] xs = {new Character('A')};
int x = xs[0] - 1;
Am I right? I cannot find document about result type and conversion of Java array's operator [].
What is the return type of Java built-in array's access operator when contains primitive type?
It is the primitive type; e.g. for an int[] it is int, for a char[] it is char and so on.
However, I think you are getting yourself rather confused here.
All Java arithmetic operators applied to operands of type byte, char, short or int (or their wrapper types) always produce an int result. So, the expression types of 'A' - 1 and new Character('A') - 1 and xs[0] - 1 are all int.
That is why you get an errors here:
char a = 'A';
char[] a2 = {'A'};
char b = a + 1; // COMPILATION ERROR
char c = a2[0] + 1; // COMPILATION ERROR
char d = new Character('A') + 1; // COMPILATION ERROR
You need type casts to make those assignments work.
So why don't you get a compilation error with the following one?
char x = 'A' - 1;
In short, because 'A' - 1 is a (compile time) constant expression whose (int) value will fit into a char without any loss or information.
There is a special rule for the assignment operator that says:
IF the LHS type is byte, char or short, AND
IF the RHS expression type is int, AND
IF the RHS expression is a compile time constant expression, AND
IF the value of the RHS expression is in the range of the LHS type,
THEN there is an implicit conversion from int to the LHS type.
The above is a simplification of the JLS rules ... which include a precise specification of what a constant expression is.
Intuitively, the compiler allows you to leave out the type cast because it "knows" that a type cast would not lose any information.
When array xs has primitive char values and someone try to accessing that value using [], what is the return type?
The type of the element always corresponds to the type of the reference (left hand side). Auto-boxing occurs if primitives assigned on the right where the type is Character[] or auto-unboxing if references assigned where type is char[]
You could check using instanceof Character - it will return true to verify it's a Character or compile error if it's a primitive.
char[] xs = {'A'};
System.out.println(xs[0]);
System.out.println(xs[0] instanceof Character); // COMPILE ERROR: unexpected type required: reference found: char
char[] ys = {new Character('A')};
System.out.println(ys[0]);
System.out.println(ys[0] instanceof Character); // COMPILE ERROR: unexpected type required: reference found: char
Character[] cs = {'A'};
System.out.println(cs[0] instanceof Character); // true

what is the difference between '1' - 0 and '1' - '0' [duplicate]

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.

Implicit Casting char to int and using ++ operator [duplicate]

char char1 = 'a';
System.out.println(char1); //prints char 1
System.out.println(char1+1); //prints char 1
System.out.println(char1++); //prints char 1
System.out.println(char1+=1); //prints incremented char1
char1 += 1;
System.out.println(char1); //prints incremented char1
In the above, why doesn't (char1+1) or (char++) print the incremented character but theother two do?
First, I'm assuming that because you say the increment in System.out.println works, that you have really specified:
char char1 = 'a';
EDIT
In response to the change of the question (char1+1; => char1 += 1;) I see the issue.
The output is
a
98
b
The 98 shows up because the char a was promoted to an int (binary numeric promotion) to add 1. So a becomes 97 (the ASCII value for 'a') and 98 results.
However, char1 += 1; or char1++ doesn't perform binary numeric promotion, so it works as expected.
Quoting the JLS, Section 5.6.2, "Binary Numeric Promotion":
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.
(emphasis mine)
You didn't assign the result of addition char1+1 to char1. So
char1 = char1 + 1;
or
char1 += 1;
char1++;
are correct.
Okay, first of all, fixing the format of your code:
char char1;
char1 = 'a';
System.out.println(char1); // print 1
System.out.println(char1 + 1); // print 2
char1 += 1;
System.out.println(char1); // print 3
which yields the output:
a
98
b
Now, let's look at each call to println() in detail:
1: This is simply taking the character handle named char1 and printing it. It's been assigned the letter a (note the single quotes around the a in the assignment, indicating character). Not surprisingly, this prints the character a.
2: For this line, you're performing an integer addition. A char in java is held as a unicode character. The unicode value for the letter a maps to the number 97. (Note that this also corresponds to that ASCII value for a). When performing arithmetic operations in Java between mismatched types, the smaller/less precise value type's value will be 'upgraded' to the larger type (this is very imprecisely stated). Because of this, the char is 'upgraded' to an int before the addition is performed, and the result is also an int. With this in mind, it's not surprising that the 97 from a +1 results in a 98 being printed.
3: In this instance we are once again printing the value of a char, so a character is printed. This time the 98 we saw generated before is implicitly cast back into a character. Again, unsurprisingly the next highest number mapping from a is b, so we see a b printed.
try this.
System.out.println(char1);
System.out.println(++char1);
char1 += 1;
System.out.println(char1);
instead
char1 = a;
System.out.println(char1);
system.out.println(char1+1);
char1 += 1;
System.out.println(char1);

I am confused about the data types of java.

Why is this right?
char c1 = 125;
And why is this wrong?
char c2 = c1 + 1;
The right way of the codes above should be:
char c2 = (char)(c1 + 1);
I am confused. Thank you very much!
In Java, you need to be aware of the type of the result of a binary (+) arithmetic operator.Below are the rules
1.If either operand is of type double, the other is converted to double.
2.Otherwise, if either operand is of type float, the other is converted to float.
3.Otherwise, if either operand is of type long, the other is converted to long.
4.Otherwise, both operands are converted to type int.
Your statement c1 + 1 falls into 4th rule, so the result is of type int and then you need to cast it char explicitly to assign it to char variable.
It's wrong because char is smaller than int. In c1 + 1 the c1 is promoted to an
int to be added to 1. When you try to put it back in a char java complains
because it can't promise that an int will fit in a char
-edit-
In the case of char c = 123 the 123 part is known, so java can really promise that
it will always fit in a char. This will work as well:
final char c0 = 123;
char c1 = c0 + 1;
and this:
final int i0 = 123;
char c1 = i0 + 1;
char c2 = c1 + 1;
The Java language specification defines exactly how integer numbers are represented and how integer arithmetic expressions are to be evaluated.
Arithmetic expression on the right-hand side of the assignment operator evaluates to int by default. int has bigger storage size than short. That is why you have to explicitly tell that you know what you are doing by using casting.

Categories

Resources