Distinguishing between Primitives and Reference Types – Building Blocks – 1Z0-829 Study Guide

Distinguishing between Primitives and Reference Types

There are a few important differences you should know between primitives and reference types. First, notice that all the primitive types have lowercase type names. All classes that come with Java begin with uppercase. Although not required, it is a standard practice, and you should follow this convention for classes you create as well.

Next, reference types can be used to call methods, assuming the reference is not null. Primitives do not have methods declared on them. In this example, we can call a method on reference since it is of a reference type. You can tell length is a method because it has () after it. See if you can understand why the following snippet does not compile:

  • String reference = “hello”;
  • int len = reference.length();
  • int bad = len.length(); // DOES NOT COMPILE

Line 6 is gibberish. No methods exist on len because it is an int primitive. Primitives do not have methods. Remember, a String is not a primitive, so you can call methods like length() on a String reference, as we did on line 5.

Finally, reference types can be assigned null, which means they do not currently refer to an object. Primitive types will give you a compiler error if you attempt to assign them null. In this example, value cannot point to null because it is of type int:

int value = null; // DOES NOT COMPILE

String name = null;

But what if you don’t know the value of an int and want to assign it to null? In that case, you should use a numeric wrapper class, such as Integer, instead of int.

Creating Wrapper Classes

Each primitive type has a wrapper class, which is an object type that corresponds to the primitive. Table 1.7 lists all the wrapper classes along with how to create them.

TABLE 1.7Wrapper classes
Wrapper class
Primitive typeWrapper classinherits Number?Example of creating
booleanBooleanNoBoolean.valueOf(true)
byteByteYesByte.valueOf((byte) 1)
shortShortYesShort.valueOf((short) 1)
intIntegerYesInteger.valueOf(1)
longLongYesLong.valueOf(1)
floatFloatYesFloat.valueOf((float) 1.0)
doubleDoubleYesDouble.valueOf(1.0)
charCharacterNoCharacter.valueOf(‘c’)

There is also a valueOf() variant that converts a String into the wrapper class.

For example:

int primitive = Integer.parseInt(“123”); Integer wrapper = Integer.valueOf(“123”);

The first line converts a String to an int primitive. The second converts a String to an Integer wrapper class.

All of the numeric classes in Table 1.7 extend the Number class, which means they all come with some useful helper methods: byteValue(), shortValue(), intValue(), longValue(), floatValue(), and doubleValue(). The Boolean and Character wrapper classes include booleanValue() and charValue(), respectively.

As you probably guessed, these methods return the primitive value of a wrapper instance, in the type requested.

Double apple = Double.valueOf(“200.99”);
System.out.println(apple.byteValue());// -­56
System.out.println(apple.intValue());//200
System.out.println(apple.doubleValue());//200.99

These helper methods do their best to convert values but can result in a loss of preci-sion. In the first example, there is no 200 in byte, so it wraps around to -56. In the sec-ond example, the value is truncated, which means all of the numbers after the decimal are dropped. In Chapter 5, we apply autoboxing and unboxing to show how easy Java makes it to work with primitive and wrapper values.

Some of the wrapper classes contain additional helper methods for working with num-bers. You don’t need to memorize these; you can assume any you are given are valid. For example, Integer has:

max(int num1, int num2), which returns the largest of the two numbers min(int num1, int num2), which returns the smallest of the two numbers sum(int num1, int num2), which adds the two numbers