Win a copy of Functional Reactive Programming this week in the Other Languages forum!

# question on integer promotion / assignment

Mark Neher
Greenhorn
Posts: 9
On one of Dan Chisholm's exams, there was the following line buried in a question:

char primitiveChar = 'b'-'a';

The answer indicated that this was OK. I expected a compiler failure on this line -- I thought that the literal chars would be promoted to ints, and the assignment would be flagged for not casting it back down to a char. Indeed, the K&B book outlines a similar scenario for compiler error using bytes:

byte b = 3, c = 8;
byte d = b + c;

Trying to actually compile these does allow the char case, and gives an error on the (seemingly same to me) byte case. Can anyone explain the difference ??

Thanks,

Mark

Barry Gaunt
Ranch Hand
Posts: 7729
Have you tried this?:

(gotta rush, going home time).

shandilya popuru
Ranch Hand
Posts: 95
hi mark

char is just an unsigned int as long as the value is between 0 to 65536 u dont get an error
try this u get an error
char c;
c='a'-'b';

cos the value`d be -1 out of the range of char
but this

c='b'-'a';

this`ll return 1 that`d easily fit into chars range

hope that xplains ur doubt

Mark Neher
Greenhorn
Posts: 9
OK, so

char a = 'a'; char b = 'b'; char c = b - a;

from Barry, gives a compiler error, as did

byte b = 3, c = 8; byte d = b + c;

from K & B. Further, changing K & B to

byte e = 3 + 8;

works, as did the original Dan Chisholm question of

char primitiveChar = 'b'-'a';

The pattern is clear; it still isn't obvious to me why the byte and char literals in the working examples aren't promoted to ints before the arithmetic. From K & B:

"We know that a literal integer is always an int, but more importantly -- the result of an expression involving anything int-sized or smaller is always an int. In other words, add two bytes together and you'll get an int -- even if those two bytes are tiny."

The two working examples would seem to fit this qualification: the result of an expression involving anything int-sized or smaller is always an int.

Javier Diaz
Greenhorn
Posts: 16
I *think* it is because when you use an arith expresssion that involves just constants the compiler can optimize your arithmetic so the code in the .class has not got the arith, but just the result (use javap -c <ClassName> )

So the promotion rules do not apply as there is really no operation involved ...

Test 1

char one = 'b' - 'a';

0: iconst_1 // int 1
1: istore_1
2: return

Test 2

char one = 'c' - 'a';

0: iconst_2 //int 2
1: istore_1
2: return

Test 3 (out of range, COMPILE ERROR)
The compiler checks if the result would be out of range

char one = 'a' - 'b';

Tests.java:10: possible loss of precision
found : int
required: char
char one = 'a' - 'b';

Test 4 (loop around, force)

char one = (char) ('a' - 'b');

0: ldc #2; //int 65535
2: istore_1
3: return

Hope this helps

-Javier
[ January 18, 2005: Message edited by: Javier Diaz ]

Animesh Shrivastava
Ranch Hand
Posts: 298
There is an implicit narrowing conversion from a byte, short, char, or int to a byte, short, or char when the source is a constant expression that can be evaluated at compile time and the value fits in the target. This does not apply to arguments in method invocations.

In the question given by you,
'a' and 'b' are literals which are constants,
So, it compiles fine,

Now as said by Barry,
this would give a compiler error
char a = 'a';
char b = 'b';
char c = b - a;

Because here a, b are not constants

Going through the explanation above the below would not give any compiler error,
final char a = 'a';
final char b = 'b';
char c = b - a;

See JLS 5.2 Assignment Conversion.

Mike Gershman
Ranch Hand
Posts: 1272
Animesh:

Mark Neher
Greenhorn
Posts: 9
Thanks for the answers. I was looking at the JLS yesterday, but had not yet found the relevant section.

MTN

Barry Gaunt
Ranch Hand
Posts: 7729
Now I come back and everything is done

Here's another interesting junk of JLS:

15.28 Constant Expression

ConstantExpression:
Expression

A compile-time constant expression is an expression denoting a value of primitive type or a String that is composed using only the following:

* Literals of primitive type and literals of type String
* Casts to primitive types and casts to type String
* The unary operators +, -, ~, and ! (but not ++ or --)
* The multiplicative operators *, /, and %
* The additive operators + and -
* The shift operators <<, >>, and >>>
* The relational operators <, <=, >, and >= (but not instanceof)
* The equality operators == and !=
* The bitwise and logical operators &, ^, and |
* The conditional-and operator && and the conditional-or operator ||
* The ternary conditional operator ? :
* Simple names that refer to final variables whose initializers are constant expressions
* Qualified names of the form TypeName . Identifier that refer to final variables whose initializers are constant expressions

Compile-time constant expressions are used in case labels in switch statements (�14.10) and have a special significance for assignment conversion (�5.2).

A compile-time constant expression is always treated as FP-strict (�15.4), even if it occurs in a context where a non-constant expression would not be considered to be FP-strict.

Examples of constant expressions:

true
(short)(1*2*3*4*5*6)
Integer.MAX_VALUE / 2
2.0 * Math.PI
"The integer " + Long.MAX_VALUE + " is mighty big."

ankur rathi
Ranch Hand
Posts: 3830
Mark , may be my explanation you will not like but simple one :

if you are assigning a variable into a variable ( x = y ) then you have to make sure to compiler that you will not go to the out of range of left hand side variable ( x ) .
Like this will give no error at compile time .

Andris Jekabsons
Ranch Hand
Posts: 82
Right, because "y" is a constant (by virtue of being defined "final").
Remove the "final" part, and you'll have a compile-time error.