Increment char variable by an int value [duplicate] - java

This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Closed 7 years ago.
I wrote two versions of Java code to increment a char variable by 1:
version1:
char c = 'a';
c = c + 1;
version2:
char c = 'a';
c += 1;
To my surprise, the second version compiles and runs successfully but the first one shows an error, which says incompatible types: lossy conversion from int to char. Why are they different?

The second version involves a cast, and is equivalent to:
c = (char) (c + 1);
See JLS section 15.26.2 (Compound operators):
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Related

Ternary operator returns an unexpected output [duplicate]

This question already has an answer here:
What is the type of a ternary expression with int and char operands? [duplicate]
(1 answer)
Closed 2 years ago.
This subject is already asked but I didn't understand it.
You'll find my program below. When I run this program it prints X and 88. When I remove do the declaration of int i = 0 it returns X and X. I found some explanations here : Unexpected output when using a ternary operator and final variable but i didn't understand it so much. I don't understand why this program returns X and 88 instead of X and X.
public class Ternary {
public static void main(String[] args) {
char x = 'X';
int i = 0;
System.out.println(true ? x : 0);
System.out.println(false ? i : x);
}
}
please read the rules of ternary operator here
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
1st one is result of If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression of type int whose value is representable in type T, then the type of the conditional expression is T. T being type char in this case and constant expression being 0
so the output is of type char which is x
2nd one is case for Otherwise, binary numeric promotion is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
read about binary numeric promotion here https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
last case of point 2 applies here Otherwise, both operands are converted to type int. and converting char to int gives its ascii value which is 88
and hence the output is 88

Incompatible types. Required: short, Found: int [duplicate]

This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Adding int to short [duplicate]
(3 answers)
short plus short is an int [duplicate]
(2 answers)
Closed 4 years ago.
I just can't understand the difference between this:
short d = 0;
//some code
node.accessible = d + 1;
and this
short d = 0
//same code here
node.accessible = d;
node.accessible += 1;
the second thing is working, but the 1st one is't inteliji showes "incompatiable types" error.
p.s. node class:
public class Node {
int n;
short accessible;
Node(int n){
this.n = n;
this.accessible = -1;
}
}
In the first version :
node.accessible = d + 1;
d + 1 produces a int as summing an int and a short produces an int.
The JLS states indeed that (look at the last case, emphasis is mine) :
5.6.2. Binary Numeric Promotion
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:
If any operand is of a reference type, it is subjected to unboxing
conversion (§5.1.8).
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.
But you cannot assign a int to the accessible field that is a short without explicit cast as int has a broader range than short.
While in the second version, a Compound Assignment Operators is used (+=):
node.accessible += 1;
As a consequence, in your case the result of the operation is converted to short : the type of the left-hand variable as the JLS states :
15.26.2. Compound Assignment Operators
A compound assignment expression of the form E1 op= E2 is equivalent
to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1
is Evaluations only once.
And more specifically in your case :
Otherwise, the result of the binary operation is converted to the type
of the left-hand variable, subjected to value set conversion (§5.1.13)
to the appropriate standard value set (not an extended-exponent value
set), and the result of the conversion is stored into the variable.
That's because 1 in your + 1 expression is of type int. Adding short to int results in int which can't be assigned without a narrowing cast back to node.accessible.
In the second sample,
node.accessible += 1;
is actually
node.accessible = (short)(node.accessible + 1);
so it works without problem.
But in the first one
node.accessible = d + 1; is actually node.accessible = d + 1; and it doesn't automatically cast as short and thus gives error as (d + 1) is of type int

Why xor operation on constants (character) is working differently when used variables in its place [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Have a look at the following code :
Case 1 :
char a = 'x' ^ 'y';
It is working fine.
But when I use variable instead of constants as here :
Case 2:
char x = 'x';
char y = 'y';
char a = x ^ y; // Error!
In java language : case 1 is working and value of a comes out to be 1 but case 2 is not working.
In C and C++ : both cases are working, and the value of a comes out to be 1
In C# : both the cases are not working.
In javascript : both cases are working, which is not a HLL, and value of a comes out to be 0.
I understand that java is converting variables to integer to do binary operation, but why it is working in case 1 and not in case 2, Why same is not working in C# And why the values are different in the case of javascript.
Updated
When I made the variables final than it is working in java, but still not in C#
final char x = 'x';
final char y = 'y';
char a = x ^ y;
But still I cannot understand why constants are working but when using variable they are not. And why same is not happening with other high level programming language.
I think it is a basic operation and should be working in all programming languages with same behaviour.
Note To test all above cases in javascript I am replacing 'char' with 'var' in all cases and they are working.
Answering for Java only.
The expression 'x' ^ 'y' is a constant expression; x ^ y is not, unless both variables are declared final. Furthermore, the result is an int; ^ is an integral bitwise operator, meaning that both operands have to be promoted to an integral type before being evaluated. char promotes to int.
So you have this int expression, and you try to narrow it to a char. In the general case, this could lead to a loss of precision (ints are 4 bytes, chars are 2), so the compiler doesn't let you do that without you explicitly stating it's what you want to do (via a cast to char). However, you can implicitly narrow constant expressions, if their value would fit into the new type. From JLS 5.2:
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.
(Emphasis added)
Intuitively, this makes total sense: the error is there to tell you that you may lose precision, and so it wants you to confirm that you know that; in a sense, it's a loud warning. But if the compiler can know absolutely that this won't happen, as it can for a constant expression, then it makes things a bit easier for you and "hides" that warning.
I will consider C languages that is C, C++ and C#.
In C# there is no implicit conversion from an integral type to type char. According to section "11.1.5 Integral types" of the ECMA 334 Standard "C# Specification"
• There are no implicit conversions from other types to the char type.
In particular, even though the sbyte, byte, and ushort types have
ranges of values that are fully representable using the char type,
implicit conversions from sbyte, byte, or ushort to char do not exist.
So you need explicitly to cast the result of the operator to type char. For example
using System;
namespace ExclusiveOr
{
class Program
{
static void Main(string[] args)
{
char a = ( char )('x' ^ 'y' );
char c = 'x', d = 'y';
char b = ( char )( c ^ d );
Console.WriteLine("a = {0}, b = {1}", (int)a, (int)b);
}
}
}
The output is
a = 1, b = 1
According to the C Standard (section 6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals
So for example this code will be compiled
#include <stdio.h>
char a = 'x' ^ 'y';
int main(void)
{
printf( "a = %d\n", a );
return 0;
}
The output is
a = 1
However this code will not be compiled
#include <stdio.h>
char c = 'x';
char d = 'y';
char b = c ^ d;
int main(void)
{
printf( "b = %d\n", b );
return 0;
}
will not be compiled. The GCC compiler will issue error
prog.c:8:1: error: initializer element is not constant char b = c ^ d;
However if you will make varaible b local then the code will be compiled successfully
#include <stdio.h>
char c = 'x';
char d = 'y';
int main(void)
{
char b = c ^ d;
printf( "b = %d\n", b );
return 0;
}
The output is
b = 1
In C++ there is no such a restriction for objects with the static storage duration so all examples of programs similar to C programs showed above will be compiled.
Under normal circumstances, the operands of the following binary operators are "widened" before the operation is performed.
(From the JLS 5.6.1)
The multiplicative operators *, /, and % (§15.17)
The addition and subtraction operators for numeric types + and - (§15.18.2)
The numerical comparison operators <, <=, >, and >= (§15.20.1)
The numerical equality operators == and != (§15.21.1)
The integer bitwise operators &, ^, and | (§15.22.1)
In certain cases, the conditional operator ? : (§15.25)
In the case of char operands, widening will convert the operands to int.
For the arithmetic and bitwise operations, the type of the operation's result is the same as the "wider" of the two operands.
When x and y have type char, the expression x ^ y gives you an int value. That can't be assigned back to a char without a type cast, and hence you get a compilation error.
For the case where you are using char literals, the same widening process happens. But there is a "special exception" in the language which allows the value of a constant expression to be implicitly narrowed, provided that the constant expression's value will fit into the type. In this case, 'x' ^ 'y' will "fit" into a char, so the assignment is allowed.
The JLS reference for this exception for constant expressions is JLS 5.2.

final characters in Java [duplicate]

This question already has answers here:
Why can not I add two bytes and get an int and I can add two final bytes get a byte?
(3 answers)
Java - char, int conversions
(4 answers)
Closed 8 years ago.
The following segment of code issues a compile-time error.
char c = 'c';
char d = c + 5;
The error on the second line says,
possible loss of precision
required: char
found: int
The error message is based on the NetBeans IDE.
When this character c is declared final like as follows.
final char c = 'c';
char d = c + 5;
The compiler-time error vanishes.
It is unrelated to the case of final strings
What does the final modifier make a difference here?
The reason is that the JLS #5.2 (Assignment conversion) says so:
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.
In your example, char c = 'c'; is not a constant but final char c = 'c'; is.
The rationale is probably that the addition operator + first converts its operands to integers. So the operation could overflow unless everything is constant in which case the compiler can prove that there is no overflow.
When you apply the + operator to integral types
Binary numeric promotion is performed on the operands (§5.6.2).
In this case, the char values are promoted to int values.
Here
char c = 'c';
char d = c + 5;
because c is not a constant expression, the compiler cannot determine if the value of c + 5 which is an int will be able to fit in a char.
In this
final char c = 'c';
char d = c + 5;
where c is a constant expression, the compiler can determine that the value of c, which is 99, added to 5, which is 104 does fit in a char. Because of this guarantee, Java can safely perform a narrowing conversion from int to char.
If instead you had
final char a = Character.MAX_VALUE;
char b = (a + 5);
you would see the similar behavior as your first test case as the value of a + 5 does not fit in a char. The compiler determines that the int value resulting from a + 5 would not fit in a char.

Java += compiler/jre bug? [duplicate]

This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Closed 9 years ago.
I encountered someting unexpected with the java += operator.
Apparently, this compiles:
int a = 0;
a += 3/2.0;
System.out.println(a); // outputs "1"
While, this doesn't
int a = 0;
a = a + (3/2.0); // eclipse compiler error "Type mismatch: cannot convert from double to int"
System.out.println(a);
Is this expected behaviour? I find it strange that the += operator does not report a "Type mismatch", because it is an 'add and assign' operator, where you add a double, which gives a double result, and is then assigned to an int variable. Instead it silently casts (and truncates) the result.
This is the way += has worked from C. It's "feature" not a bug
See Java's +=, -=, *=, /= compound assignment operators
BTW You can try this
char ch = '0';
ch *= 1.1; // ch = '4'
Also see a post of mine http://vanillajava.blogspot.com/2012/11/java-and-implicit-casting.html
int a = a + (3/2.0); doesn't compile since:
int + double leads to a double
a is referenced as an int
cast from double to int missing
int a += 3/2.0; compiles since:
int + double leads to a double
a is referenced as an int
double is castable to an int and luckily, compiler adds an implicit cast similar to:
int a = (int)(a+ 3/2.0);. This is due to the special op= notation that is interpreted more cleverly from compiler than the basic assignment operator: =.
This is not a bug , its a implicit conversion happened.
for eg.
Byte b=3;
b+=5; //compiles
b=b+5; //doesnt compiles
Here what happens is
a=a+3/2.0; // 3/2.0 produces double , it add int to double but cant convert it implicitly to int.
a += 3/2.0; // here implicit conversion after addition of a to 3/2.0 happends from double to int

Categories