Search code examples
javaimplicit-conversion

Query about Implicit Type casting in Java for Primitive data types


I HAVE BEEN LEARNING ABOUT TYPE CASTING IN JAVA AND THIS HAPPENED.

First I gave a large value to an integer variable(larger number than the range of byte data_type). Next I created a byte variable and tried to type cast the value of first variable. Clearly this should raise an error as the range of the byte is shorter than the value of first variable.I did this in JSHELL.

Screenshot of my problem

I wish to know why java didnt give me an error and instead gave a completely different number.I didnt see any byte wraparounds as the result value is much larger.


Solution

  • First, let me explain why you get 44 when casting 300 to a byte. To do so, I need to start by explaining integer representation in memory. Java, as most programming language, represents signed integers using two's complement. Simply put, every number is represented given a fixed number of binary digits (bits) n, where the first represents the sign and the n-1 others represent the magnitude. For positive numbers, those n-1 bits is simply the number in binary.

    The main difference between Java's integer types is this n: ints work over n = 32 bits whereas bytes use n = 8 bits. This means that your number 300 is represented as 0000'0000'0000'0000'0000'0001'0010'1100 in memory. Now, you want to translate this number to a representation which uses only 8 bits, though you can clearly see that you need at least 10 of them (9 for the magnitude, and 1 for the sign). You will thus need to have some loss of information. Java does not consider this problem (in fact, there is no way for it to do so) and simply copies the 8 right-most bits, to give 0010'1100. Translating this to base 10 indeed yields 44.

    Notice that, if you know binary, in the conversion from int to byte, you lost a 1 in the 256 place. This may give you more intuition on why 300 - 44 = 256.

    Second, let's speak about the fact Java does not give you an error. Notice first that the following code does not compile since an int can hold bigger values than a byte can:

    int myfirstnumber = 100;
    byte mysecondnumber = myfirstnumber;  // error: incompatible types: possible lossy conversion from int to byte
    

    The compiler refues to let you do a narrowing conversion without you acknowledging it; it considers that such syntax is too error-prone. However, you may sometimes want to do such a conversion. In this case, you have to show that this is indeed your intention:

    int myfirstnumber = 100;
    byte mysecondnumber = (byte)myfirstnumber;
    

    In this case, the compiler thinks you know what you are doing, as @old-dog-programmer pointed out. Now, if you don't want to loose data when doing your cast, you should make the verification that there would be an overflow yourself:

    int myfirstnumber = 100;
    byte mysecondnumber = 0;
    if(Byte.MIN_VALUE <= myfirstnumber && myfirstnumber <= Byte.MAX_VALUE) {
        mysecondnumber = (byte)myfirstnumber;
    } else {
        // handle the error
    }