4

I`m learning Java with the Herbert Schildt book's: Java a Beginner's Guide. In that book appears this code:

// A promotion surprise!
class PromDemo{
    public static void main(String args[]){
        byte b;
        int i;
        b = 10;
        i = b * b;      // OK, no cast needed

        b = 10;
        b = (byte) (b * b);     // cast needed!!

        System.out.println("i and b: " + i + " " + b);
    }
}

I don't understand why I must use (byte) in the line:

b = (byte) (b * b);     // cast needed!!

b was defined as a byte and the result of b * b is 100 which is right value for a byte (-128...127).

Thank you.

Danielson
  • 2,605
  • 2
  • 28
  • 51
Euriloco
  • 253
  • 1
  • 4
  • 9
  • 2
    In your case it is OK, but what if result would be out of `byte` range? Remember that compiler can't assume values of non-final variables. – Pshemo Jun 26 '15 at 15:06
  • @Pshemo why then does multiplying two `int`s not require a cast? – xrisk Jun 26 '15 at 15:10
  • @RishavKundu I can't find any resource now but I am guessing that since most of the time programmers are dealing with ***small*** `int`s compiler assumes that risk of overflow is minimal, but even if it occurs programmers are aware of it so there is no point in reminding them about it. Anyway compiler **needs** to stop informing programmer about possibility of overflow somewhere. Lets say that `int*int` generates `long`. Compiler will need to inform us about possible lost of precision. But what should it do in case of `long*long`? (there needs to be some place where it assumes that *we know*). – Pshemo Jun 26 '15 at 15:18
  • You'll be more surprised by `b=b+1;` :) – ZhongYu Jun 26 '15 at 15:35
  • avoid `byte` if you can. see http://stackoverflow.com/questions/6892444/are-there-any-real-life-uses-for-the-java-byte-primitive-type/6895113#6895113 – ZhongYu Jun 26 '15 at 15:36

2 Answers2

7

The JLS (5.6.2. Binary Numeric Promotion) gives rules about combining numeric types with a binary operator, such as the multiplication operator (*):

  • If either of the operands is of type double, the other one will be converted to a double.
  • Otherwise, if either of the operands is of type float, the other one will be converted to a float.
  • Otherwise, if either of the operands is of type long, the other one will be converted to a long.
  • Otherwise, both operands will be converted to an int.

The last point applies to your situation, the bytes are converted to ints and then multiplied.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
yas
  • 3,520
  • 4
  • 25
  • 38
  • it doesn't matter that i declared b as a byte. It will be converted to int due to *. is it correct? Thank you. – Euriloco Jun 26 '15 at 15:30
  • 1
    Yes, that is correct - since the first 3 conditions listed above have not been met, the last case applies of converting the byte operands to integers. – yas Jun 26 '15 at 15:37
3

In Java, byte and short will always be promoted to int, when you have a calculation like this:

byte b = 10;
b = (byte) (b * b);

So you actually multiply an integer with an integer, which will return an integer. Since you cannot assign an integer to a byte, you need the cast.

This is called "automatic type promotion" if you would like to Google it (to find e.g. https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2)

Thomas Uhrig
  • 30,811
  • 12
  • 60
  • 80
  • [This would be a better reference.](https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2) – Makoto Jun 26 '15 at 15:15
  • Thank you, it is of course! Quote from 5.6.2 point 2: "Otherwise, both operands are converted to type int." - which applies to byte and char. Thanks for your hint :) – Thomas Uhrig Jun 26 '15 at 15:17
  • Sure. I encourage you to add it to your answer as opposed to whatever other reference you've Googled. JLS references are *always* more concrete. – Makoto Jun 26 '15 at 15:21
  • I don' t understand why I am multiplying an integer with an integer. – Euriloco Jun 26 '15 at 15:28
  • @Euriloco: Follow the link to the language specification. It's a fall-back case. – Makoto Jun 26 '15 at 15:28