The SCJP Tip Line
More About Conversions
by Corey McGlone

This month we're going to do a quick extension of my last article. In that article, we looked at the various types of conversion and casts that can be done in Java. This week, I'm going to look at a specific trick with casting that may very well appear on the exam - it most certainly appears on most mock exams.

Assignment Conversion vs. Method Invocation Conversion

Let's start off by taking a look at this code snippet:
Source Code
            
public class Conversions
{
    private static byte myMethod(byte b)  // 1
    {
        return 32;  // 2
    }
 
    public static void main(String[] args)
    {
        byte b = myMethod(50);  // 3
        System.out.println(b);  // 4
    }
}
            

So what's the output of that code? I sure hope you said that it produces a compiler error, because it certainly does. Let's take a look at all of the conversions that are taking place in that code - believe me, there are a lot.

Let's start at Line 3, which is the first line that will be executed. What data type is 50? Any integral literal is always considered an int by the compiler. Therefore, line 3 is passing an int to a method that takes a byte as a parameter. This is where our compiler error comes from. Passing a parameter to a method invokes a Method Invocation Conversion. A method invocation conversion can only perform an identity conversion (such as casting a byte to a byte, which is trivial) or a widening conversion. Obviously, casting an int to a byte is a narrowing conversion, so the method invocation conversion can't handle it. Hence, the compiler error. If we were passing a byte to a method that took an int, no problem - that's a widening conversion. But an int to a byte? That's a no-no. Let's modify line 3 to read like this:

byte b = myMethod((byte)50);

What does that do for us? Well, by first casting the int to a byte (through our explicit cast), we are passing a byte to a method that requires a byte. That's just an identity conversion so the method invocation conversion works just fine.

So now let's jump to Line 2. There's a conversion happening here, as well. What type is 32? Obviously, 32 is an int, just as we saw that 50 was an int. What conversion is happening here? Well, look at the return type of that method - we're supposed to return a byte. But we're returning an int! That should cause a compiler error, right? Wrong. Rather than using a method invocation conversion to perform the conversion, the compiler is going to use an Assignment Conversion (essentially assigning the value being returned to the return variable). There's a trick to an assignment conversion, though - the following comes straight from the JLS:

"Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of an identity conversion (§5.1.1), a widening primitive conversion (§5.1.2), or a widening reference conversion (§5.1.4). In addition, a narrowing primitive conversion may be used if all of the following conditions are satisfied:
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."


Essentially, that says that you can automatically assign a value to a variable, even if that assignment would require a narrowing conversion, as long as the value is known at compile time (a literal value, as we have here, or a final variable) and that value "fits" into the target type. In our case, we're trying to assign 32 to a byte. Well, 32 is a literal, so we know the type at compile time and it certainly falls within the range of a byte, which is from -128 to 127. Therefore, the Assignment Conversion handles this conversion automatically by doing an automatic narrowing cast.

Conclusion

Short update this week, but an important one. The differences between method invocation conversions and assignment conversions are small, but important. Certainly, such details about conversions can be considered "nit-picking" but a lot of the SCJP exam falls into that realm. The idea behind the SCJP exam is to have a good handle on the details of the language and I've seen questions about this material on many mock exams and the real SCJP exam.

Until next time,
Corey