long
takes up more space than an int
, which in turn takes up more space than a short
, and so on.
You need to memorize certain rules that Java will follow when applying operators to data types:
Numeric Promotion Rules
1 If two values have different data types, Java will automatically promote one of the values to the larger of the two data types.
2 If one of the values is integral and the other is floating-point, Java will automatically promote the integral value to the floating-point value's data type.
3 Smaller data types, namely, byte, short, and char, are first promoted to int any time they're used with a Java binary arithmetic operator with a variable (as opposed to a value), even if neither of the operands is int.
4 After all promotion has occurred and the operands have the same data type, the resulting value will have the same data type as its promoted operands.
The last two rules are the ones most people have trouble with and the ones likely to trip you up on the exam. For the third rule, note that unary operators are excluded from this rule. For example, applying ++
to a short
value results in a short
value.
Let's tackle some examples for illustrative purposes:
What is the data type of x * y?int x = 1; long y = 33; var z = x * y;
In this case, we follow the first rule. Since one of the values is int and the other is long, and long is larger than int, the int value x is first promoted to a long. The result z is then a long value.
What is the data type of x + y?double x = 39.21; float y = 2.1; var z = x + y;
This is actually a trick question, as the second line does not compile! As you may remember from Chapter 1, floating-point literals are assumed to be double unless postfixed with an f, as in 2.1f. If the value of y was set properly to 2.1f, then the promotion would be similar to the previous example, with both operands being promoted to a double, and the result z would be a double value.
What is the data type of x * y?short x = 10; short y = 3; var z = x * y;
On the last line, we must apply the third rule: that x and y will both be promoted to int before the binary multiplication operation, resulting in an output of type int. If you were to try to assign the value to a short variable z without casting, then the code would not compile. Pay close attention to the fact that the resulting output is not a short, as we'll come back to this example in the upcoming “Assigning Values” section.
What is the data type of w * x / y?short w = 14; float x = 13; double y = 30; var z = w * x / y;
In this case, we must apply all of the rules. First, w will automatically be promoted to int solely because it is a short and is being used in an arithmetic binary operation. The promoted w value will then be automatically promoted to a float so that it can be multiplied with x. The result of w * x will then be automatically promoted to a double so that it can be divided by y, resulting in a double value.
When working with arithmetic operators in Java, you should always be aware of the data type of variables, intermediate values, and resulting values. You should apply operator precedence and parentheses and work outward, promoting data types along the way. In the next section, we'll discuss the intricacies of assigning these values to variables of a particular type.
Assigning Values
Compilation errors from assignment operators are often overlooked on the exam, in part because of how subtle these errors can be. To be successful with the assignment operators, you should be fluent in understanding how the compiler handles numeric promotion and when casting is required. Being able to spot these issues is critical to passing the exam, as assignment operators appear in nearly every question with a code snippet.
Assignment Operator
An assignment operator is a binary operator that modifies, or assigns, the variable on the left side of the operator with the result of the value on the right side of the equation. Unlike most other Java operators, the assignment operator is evaluated from right to left.
The simplest assignment operator is the =
assignment, which you have seen already:
int herd = 1;
This statement assigns the herd
variable the value of 1
.
Java will automatically promote from smaller to larger data types, as you saw in the previous section on arithmetic operators, but it will throw a compiler exception if it detects that you are trying to convert from larger to smaller data types without casting. Table 2.5 lists the first assignment operator that you need to know for the exam. We present additional assignment operators later in this section.
TABLE 2.5 Simple assignment operator
Operator | Example | Description |
---|---|---|
Assignment |
int a = 50;
|
Assigns the value on the right to the variable on the left |
Casting Values
Seems easy so far, right? Well, we can't really talk about the assignment operator in detail until we've covered casting. Casting is a unary operation where one data type is explicitly interpreted as another data type. Casting is optional and unnecessary when converting to a larger or widening data type, but it is required when converting to a smaller or narrowing data type. Without casting, the compiler will generate an error when trying to put a larger data type inside a smaller one.
Casting is performed by placing the data type, enclosed in parentheses, to the left of the value you want to cast. Here are some examples of casting:
int fur = (int)5; int hair = (short) 2; String type = (String) "Bird"; short tail = (short)(4 + 10); long feathers = 10(long); // DOES NOT COMPILE
Spaces between the cast and the value are optional. As shown in the second-to-last example, it is common for the right side to also be in parentheses. Since casting is a unary operation, it would only be applied to the 4
if we didn't enclose 4 + 10
in parentheses. The last example does not compile because the type is on the wrong side of the value.
On the one hand, it is convenient that the compiler automatically casts smaller data types to larger ones. On the other hand, it makes for great exam questions when they do the opposite to see whether you are paying attention. See if you can figure out why none of the following lines of code compile:
float egg = 2.0 / 9; // DOES NOT COMPILE int tadpole = (int)5 * 2L; // DOES NOT COMPILE short frog = 3 - 2.0; // DOES NOT COMPILE
All of these examples involve putting a larger value into a smaller data type. Don't worry if you don't follow this quite yet; we cover more examples like this shortly.
In this chapter, casting is primarily concerned with converting numeric data types into other data types. As you will see in later chapters, casting can also be applied