9

Could someone explain the java byte type?

This doesn't compile:

byte b1 = 9;
byte b2 = 1;
byte b3 = b1 + b2;

While this does:

byte b4 = 9 + 1;
byte b5 = (char)(9+1);

In addition, assignment to a long doesn't work, even if the value fits into a byte:

byte b7 = (long)127;

It gets even weirder with wrappers

This compiles:

Byte b6 = (int)3;

But this doesn't:

Integer i = (byte)3;
Andrew Liu
  • 666
  • 4
  • 7
  • 1
    Without the error messages and line numbers of the complaints, this is rather hard to answer. – bmargulies Feb 20 '12 at 18:26
  • Also, `byte x = 126 + 1;` works but not `byte y = 126 + 2;` Somehow, when using a computable value, the compiler checks if the container is wide enough. Can't find the ref in the JLS, though. – gawi Feb 20 '12 at 18:40
  • This is discussed at length in the answers to this question: [link](http://stackoverflow.com/questions/81392/java-why-do-i-receive-the-error-message-type-mismatch-cannot-convert-int-to-b) – Skip Head Feb 20 '12 at 18:49
  • JLS 5.2: Assignment conversion – 0x434D53 Feb 20 '12 at 18:55
  • `byte b7 = (long)127;` doesn't compile, even though 127 can fit into a byte – Andrew Liu Feb 20 '12 at 19:01
  • 1
    Yes, because JLS 5.2 says, that a narrowing conversation is only done for byte, short, char and int. Long is special in that regard. – 0x434D53 Feb 20 '12 at 19:16
  • I ask some colleage tomorrow about it. I give up so far, tried some stuff, but the byte to Integer Boxing is weird... – 0x434D53 Feb 20 '12 at 21:13

3 Answers3

8

Java Language Specification 5.6.2 Binary Numeric Promotion: "Otherwise, both operands are converted type int".

So Java converts both operands to and int, so the result of the addition is an int.

Addition: The difference between b3 and b4 is, that in b4 it's an Constant Expression (15.28), in b3 it's literal.

TacticalCoder
  • 6,275
  • 3
  • 31
  • 39
0x434D53
  • 1,425
  • 12
  • 20
  • JVM Spec, has all you need. http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#16021 – jn1kk Feb 20 '12 at 18:48
  • What's going on with the wrapper classes though? It seems counter intuitive that an int can fit into a Byte, but a byte cannot fit into an Integer – Andrew Liu Feb 20 '12 at 19:05
  • Still trying to figure out the Wrappers. It's quite hard to figure out what whould happen from the specs. – 0x434D53 Feb 20 '12 at 19:30
  • The wrapper behavior relies on the fact that integer literals are handled specifically by the compiler (ie a integer literal that fits into the byte range can be used as a byte). If you use 128+ or assign it to a variable beforehand it stops to work. And no, don't ask me where that's described in the JLS :) – Voo Feb 20 '12 at 23:28
3

b6 does work due to compile-time narrowing of literal constants. b7 does not work because compile-time narrowing is limited to all primitives but long (kind of strange, no idea why)

The interesting part is §5.2 of the JLS:

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.

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

No idea why i does not work though - widening should work just fine and in fact, the compiler should generate something like Integer.valueOf((byte)3); anyhow. Using the explicit call works as expected, i.e. widening is happening.

Interestingly enough using the eclipse Java compiler Integer i = (byte) 3; compiles just fine, which leads me to believe you just found a bug in javac - congratulations! (well either that or a bug in the eclipse compiler; but eclipse's behavior seems the correct one to me). FWIW I've reported the bug against javac to oracle..

Finding the right part in the JLS was less work than formatting this that it's somewhat readable - so probably easier if you follow the link instead.

Voo
  • 29,040
  • 11
  • 82
  • 156
  • The i also confused me... I guessed it would be translated to something like = new Integer((byte)3)); But that would actually work... I just guess it's not really clarified in the JLS – 0x434D53 Feb 21 '12 at 04:23
  • @CSE No, the compiler uses the `valueOf` method (as should anyone using the Wrapper APIs, the constructor really shouldn't be public), but yes it seems like a bug to me because the explicit call actually works. [Here's](http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7147289) the bugreport, still not reviewed by oracle though as of writing - will probably take a few days. – Voo Feb 21 '12 at 04:24
-1

First snippet produces compilation error due to all numeric constants by default are ints in java.

Roman
  • 64,384
  • 92
  • 238
  • 332