Fundamental Types - Language - Java 8 Pocket Guide (2014)

Java 8 Pocket Guide (2014)

Part I. Language

Chapter 3. Fundamental Types

Fundamental types include the Java primitive types and their corresponding wrapper classes/reference types. Java 5.0 and beyond provide for automatic conversion between these primitive and reference types through autoboxing and unboxing. Numeric promotion is applied to primitive types where appropriate.

Primitive Types

There are eight primitive types in Java; each is a reserved keyword. They describe variables that contain single values of the appropriate format and size; see Table 3-1. Primitive types are always the specified precision, regardless of the underlying hardware precisions (e.g., 32- or 64-bit).

Table 3-1. Primitive types

Type

Detail

Storage

Range

boolean

true or false

1 bit

Not applicable

char

Unicode character

2 bytes

\u0000 to \uFFFF

byte

Integer

1 byte

–128 to 127

short

Integer

2 bytes

–32768 to 32767

int

Integer

4 bytes

–2147483648 to 2147483647

long

Integer

8 bytes

–263 to 263 –1

float

Floating point

4 bytes

1.4e–45 to 3.4e+38

double

Floating point

8 bytes

5e–324 to 1.8e+308

TIP

Primitive types byte, short, int, long, float, and double are all signed. Type char is unsigned.

Literals for Primitive Types

All primitive types except boolean can accept character, decimal, hexadecimal, octal, and Unicode literal formats, as well as character escape sequences. Where appropriate, the literal value is automatically cast or converted. Remember that bits are lost during truncation. The following is a list of primitive assignment examples:

boolean isTitleFight = true;

The boolean primitive’s only valid literal values are true and false.

char [] cArray = {'\u004B', 'O', '\'', 0x0064, 041,(char) 131105, 0b00100001}; // KO'd!!!

The char primitive represents a single Unicode character. Literal values of the char primitive that are greater than two bytes need to be explicitly cast.

byte rounds = 12, fighters = (byte) 2;

The byte primitive has a four-byte signed integer as its valid literal. If an explicit cast is not performed, the integer is implicitly cast to one byte.

short seatingCapacity = 17157, vipSeats = (short) 500;

The short primitive has a four-byte signed integer as its valid literal. If an explicit cast is not performed, the integer is implicitly cast to two bytes.

int ppvRecord = 19800000, vs = vipSeats, venues = (int) 20000.50D;

The int primitive has a four-byte signed integer as its valid literal. When char, byte, and short primitives are used as literals, they are automatically cast to four-byte integers, as in the case of the short value within vipSeats. Floating-point and long literals must be explicitly cast.

long wins = 38L, losses = 4l, draws = 0, knockouts = (long) 30;

The long primitive uses an eight-byte signed integer as its valid literal. It is designated by an L or l postfix. The value is cast from four bytes to eight bytes when no postfix or cast is applied.

float payPerView = 54.95F, balcony = 200.00f, ringside = (float) 2000, cheapSeats = 50;

The float primitive has a four-byte signed floating point as its valid literal. An F or f postfix or an explicit cast designates it. Even though no explicit cast is necessary for an int literal, an int will not always fit into a float where the value exceeds about 2^23.

double champsPay = 20000000.00D, challengersPay = 12000000.00d, chlTrainerPay = (double) 1300000, refereesPay = 3000, soda = 4.50;

The double primitive uses an eight-byte signed floating-point value as its valid literal. The literal can have a D, d, or explicit cast with no postfix. If the literal is an integer, it is implicitly cast.

See Chapter 2 for more details on literals.

Floating-Point Entities

Positive and negative floating-point infinities, negative zero, and Not-a-Number (NaN) are special entities defined to meet the IEEE 754-1985 standard; see Table 3-2.

The Infinity, –Infinity, and –0.0 entities are returned when an operation creates a floating-point value that is too large to be traditionally represented.

Table 3-2. Floating-point entities

Entity

Description

Examples

Infinity

Represents the concept of positive infinity

1.0 / 0.0, 1e300 / 1e–300, Math.abs (–1.0 / 0.0)

–Infinity

Represents the concept of negative infinity

–1.0 / 0.0, 1.0 / (–0.0), 1e300/–1e–300

–0.0

Represents a negative number close to zero

–1.0 / (1.0 / 0.0), –1e–300 / 1e300

NaN

Represents undefined results

0.0 / 0.0, 1e300 * Float.NaN, Math.sqrt (–9.0)

Positive infinity, negative infinity, and NaN entities are available as double and float constants:

Double.POSITIVE_INFINITY; // Infinity

Float.POSITIVE_INFINITY; // Infinity

Double.NEGATIVE_INFINITY; // –Infinity

Float.NEGATIVE_INFINITY; // –Infinity

Double.NaN; // Not-a-Number

Float.NaN; // Not-a-Number

The Double and Float wrapper classes have methods to determine if a number is finite, infinite, or NaN:

Double.isFinite(Double.POSITIVE_INFINITY); // false

Double.isFinite(Double.NEGATIVE_INFINITY); // false

Double.isFinite(Double.NaN); // false

Double.isFinite(1); // true

Double.isInfinite(Double.POSITIVE_INFINITY); // true

Double.isInfinite(Double.NEGATIVE_INFINITY); // true

Double.isInfinite(Double.NaN); // false

Double.isInfinite(1); // false

Double.isNaN(Double.NaN); // true

Double.isNaN(1); // false

Operations Involving Special Entities

Table 3-3 shows the results of special entity operations where the operands are abbreviated as INF for Double.POSITIVE_INFINITY, –INF for Double.NEGATIVE_INFINITY, and NAN for Double.NaN.

For example, column 4’s heading entry (–0.0) and row 12’s entry (\* NAN) have a result of NaN, and could be written as follows:

// 'NaN' will be printed

System.out.print((-0.0) * Double.NaN);

Table 3-3. Operations involving special entities

INF

(–INF)

(–0.0)

* INF

Infinity

–Infinity

NaN

+ INF

Infinity

NaN

Infinity

– INF

NaN

–Infinity

–Infinity

/ INF

NaN

NaN

–0.0

* 0.0

NaN

NaN

–0.0

+ 0.0

Infinity

–Infinity

0.0

+ 0.5

Infinity

–Infinity

0.5

* 0.5

Infinity

–Infinity

–0.0

+ (–0.5)

Infinity

–Infinity

–0.5

* (–0.5)

–Infinity

Infinity

0.0

+ NAN

NaN

NaN

NaN

* NAN

NaN

NaN

NaN

TIP

Any operation performed on NaN results in NaN; there is no such thing as –NaN.

Numeric Promotion of Primitive Types

Numeric promotion consists of rules that are applied to the operands of an arithmetic operator under certain conditions. Numeric promotion rules consist of both unary and binary promotion rules.

Unary Numeric Promotion

When a primitive of a numeric type is part of an expression, as listed in Table 3-4, the following promotion rules are applied:

§ If the operand is of type byte, short, or char, the type will be promoted to type int.

§ Otherwise, the type of the operand remains unchanged.

Table 3-4. Expression for unary promotion rules

Expression

Operand of a unary plus operator

Operand of a unary minus operator –

Operand of a bitwise complement operator ~

All shift operators >>, >>>, or <<

Index expression in an array access expression

Dimension expression in an array creation expression

Binary Numeric Promotion

When two primitives of different numerical types are compared via the operators listed in Table 3-5, one type is promoted based on the following binary promotion rules:

§ If either operand is of type double, the non-double primitive is converted to type double.

§ If either operand is of type float, the non-float primitive is converted to type float.

§ If either operand is of type long, the non-long primitive is converted to type long.

§ Otherwise, both operands are converted to int.

Table 3-5. Operators for binary promotion rules

Operators

Description

+ and –

Additive operators

*, /, and %

Multiplicative operators

<, ⇐, >, and >=

Comparison operators

== and !=

Equality operators

&, ^, and |

Bitwise operators

? :

Conditional operator (see next section)

Special Cases for Conditional Operators

§ If one operand is of type byte and the other is of type short, the conditional expression will be of type short:

short = true ? byte : short

§ If one operand R is of type byte, short, or char, and the other is a constant expression of type int whose value is within range of R, the conditional expression is of type R:

short = (true ? short : 1967)

§ Otherwise, binary numeric promotion is applied and the conditional expression type will be that of the promoted type of the second and third operands.

Wrapper Classes

Each of the primitive types has a corresponding wrapper class/reference type, which is located in package java.lang. Each wrapper class has a variety of methods, including one to return the type’s value, as shown in Table 3-6. These integer and floating-point wrapper classes can return values of several primitive types.

Table 3-6. Wrapper classes

Primitive types

Reference types

Methods to get primitive values

boolean

Boolean

booleanValue()

char

Character

charValue()

byte

Byte

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

short

Short

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

int

Integer

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

long

Long

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

float

Float

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

double

Double

byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()

Autoboxing and Unboxing

Autoboxing and unboxing are typically used for collections of primitives. Autoboxing involves the dynamic allocation of memory and initialization of an object for each primitive. Note that the overhead can often exceed the execution time of the desired operation. Unboxing involves the production of a primitive for each object.

Computationally intensive tasks using primitives (e.g., iterating through primitives in a container) should be done using arrays of primitives in preference to collections of wrapper objects.

Autoboxing

Autoboxing is the automatic conversion of primitive types to their corresponding wrapper classes. In this example, the prizefighter’s weight of 147 is automatically converted to its corresponding wrapper class because collections store references, not primitive values:

// Create hash map of weight groups

HashMap<String, Integer> weightGroups

= new HashMap<String, Integer> ();

weightGroups.put("welterweight", 147);

weightGroups.put("middleweight", 160);

weightGroups.put("cruiserweight", 200);

The following example shows an acceptable but not recommended use of autoboxing:

// Establish weight allowance

Integer weightAllowanceW = 5; //improper

TIP

For these examples, wrapper class variables end with a capital W. This is not the convention.

As there is no reason to force autoboxing, the preceding statement should instead be written as follows:

Integer weightAllowanceW = new Integer (5);

Unboxing

Unboxing is the automatic conversion of the wrapper classes to their corresponding primitive types. In this example, a reference type is retrieved from the hash map. It is automatically unboxed so that it can fit into the primitive type:

// Get the stored weight limit

int weightLimitP = weightGroups.get(middleweight);

TIP

For these examples, primitive variables end with a capital P. This is not the convention.

The following example shows an acceptable but not recommended use of unboxing:

// Establish the weight allowance

weightLimitP = weightLimitP + weightAllowanceW;

It is better to write this expression with the intValue() method, as shown here:

weightLimitP = weightLimitP

+ weightAllowanceW.intValue(

);