I'm gonna wrap myself in paper, I'm gonna dab myself with glue, Stick some stamps on top of my head! I'm gonna mail myself to you. | ||
--Woody Guthrie, Mail Myself to You |
The separation of primitive types (byte
, float
, and so on) and reference types (classes and interfaces) is a trade-off between efficiency and familiarity versus expressiveness and consistency. An object may incur too much overhead where a plain int
will do, while an int
may be fast and convenient until you need to store it into a hashtable. To smooth this separation, the Java programming language provides a wrapper class corresponding to each of the primitive types. Instances of a given wrapper class contain a value of the corresponding primitive type. The type hierarchy for these classes looks like this:
The language provides automatic conversion between primitives and their wrappers in many contexts, specifically when assigning values or passing arguments. For example, you can write:
Integer val = 3;
And val
will be assigned a reference to an instance of the Integer
class that holds the value 3.
Converting a primitive value to a wrapper object is known as a boxing conversion; unsurprisingly, extracting a primitive value from a wrapper object is known as an unboxing conversion.[1] The details of these conversions are discussed in “Boxing Conversions” on page 198. These automated conversions make it easy to write general purposes classes that are written in terms of Object
references, but that can handle either reference types or primitive types. The HashMap
class, for example, stores only references, not primitive types—see “HashMap” on page 590—but an int
can be passed as a key because it will be converted to an Integer
instance:
The efficiency and convenience of using an int
can be maintained, while an object can still be obtained when necessary—the best of both worlds.
A second purpose of the wrapper classes is to provide a home for methods and variables related to the type (such as string conversions and value range constants). Here, for example, is how you might check whether you could use a faster float
calculation on a particular value or whether the value requires a larger range than a float
provides and so must be performed as a double
calculation:
double aval = Math.abs(value); if (Float.MAX_VALUE >= aval && aval >= Float.MIN_VALUE) return fasterFloatCalc((float) value); else return slowerDoubleCalc(value);
The following sections cover methods and constants specific to each particular wrapper class, but first let's look at some things that are common to most of the wrapper classes.
Except where individually noted, the following sections define constructors, constants, and methods that are defined for each of the wrapper classes. The general exception is the Void
class which supports almost nothing—see page 187.
For the constructors and methods that convert strings into values, each class defines the valid form that the string can take, and these are described in the section for each class. For the numeric types, an invalid string format results in NumberFormatException
being thrown.
The term radix, used in several places in the wrapper classes, is another word for numeric base. For example, decoding a long
in radix 8 means the same as decoding it in base 8. The allowable range for a radix is 2 through 36.
In the following, Type
refers to the wrapper class, and type
is the corresponding primitive type.
Each wrapper class defines an immutable object for the primitive value that it is wrapping. This means that once a wrapper object has been created, the value represented by that object can never be changed. So, for example, the object created by newInteger(1)
will always have the value 1, and no methods of class Integer
allow you to modify this value.
Each wrapper class has the following constructors:
A constructor that takes a value of the primitive type and creates an object of the corresponding wrapper class. The constructors Character(char)
and Integer(int)
are examples.
A constructor that converts a single String
parameter into the object's initial value (except Character
, which has no such constructor)—for example, newFloat("6.02e23")
.
Each wrapper class, Type
, also has the following methods:
public static
Type
valueOf(
type
t)
Returns an object of the specified Type
with the value t
.
public static
Type
valueOf(String str)
Returns an object of the specified Type
with the value parsed from str
. Float.valueOf("6.02e23")
and Integer.valueOf("16")
are examples. Character
does not have this method just as it does not have the string-converting constructor.
These methods may return a newly constructed instance or a cached instance. For efficiency, you should always use one of the valueOf
methods, in preference to direct construction, unless you really need distinct instances that have the same value.
Each of the wrapper classes, with the exception of Boolean
define the following three fields:
public static final
type
MIN_VALUE
The minimum value representable by this data type. For example, for Integer
this is –231.
public static final
type
MAX_VALUE
The maximum value representable by this data type. For example, for Integer
this is 231–1.
public static final int
SIZE
The number of bits used to represent a value of this type. For example, for Integer
this is 32.
All the wrapper classes define the following field:
public static final Class<
Type
>
TYPE
A reference to the Class
object that represents primitives of this type. These fields are equivalent to the Class
objects you can obtain from .class
class literal expressions as described in “Class Literals” on page 169. For example, Integer.TYPE
is the same Class
object you will get from the expression int.class
. Note that int.class
and Integer.class
yield two different Class
instances, both of type Class<Integer>
.
Each of the wrapper classes implements the Comparable<T>
interface and so defines:
public int
compareTo(
Type
other)
Returns a value less than, equal to, or greater than zero as the object on which it is invoked is less than, equal to, or greater than the object (of the same type Type
) passed as a parameter.
For the numeric types, comparison follows the normal arithmetic rules; however, the Float
and Double
classes have specific ordering properties that differ from float
and double
—see page 191. For Boolean
, the value true
is considered greater than false
—in contrast to boolean
for which the relational operators <
and >
are not defined. For Character
, the comparison is strictly numerical, with no consideration of alphabetic, or locale specific ordering.
Each class provides a method to extract the wrapped value:
public
type
type
Value()
Returns the primitive value corresponding to the current wrapper object. For example, Integer.valueOf(6).intValue()
returns 6.
And each class overrides the following members of Object
:
public String
toString()
Provides a string representation of the wrapper object's value. For the numeric classes base 10 is always used.
public boolean
equals(Object obj)
Returns true
if the two objects are the same type and wrap the same value. For example, for two Integer
objects x
and y
, x.equals(y)
is true if and only if, x.intValue()==
y.intValue()
. If obj
is not of the same type as the current object, or is null
, false
is returned.
public int
hashCode()
Returns a value-based hash code for use in hashtables.
The following additional methods convert primitive values to and from strings:
public static
type
parse
Type
(String str)
Converts the string str
to a value of the specified primitive type
. For example, Integer.parseInt("10")
returns the value 10. This is equivalent to invoking the string-converting constructor, and extracting the resulting value with type
Value()
, but without constructing an object. Character
does not have this method just as it does not have the string-converting constructor.
public static String
toString(
type
val)
Returns a string representation of the given primitive value of type type
. For example, Double.toString(0.3e2)
returns the string "30.0"
.
All wrapper classes have these methods so we do not list them in each class's description. The wrapper class's system property fetch-and-decode methods, described in “System Properties” on page 663, are not discussed in this chapter.
The Void
class is the exception to all the preceding rules because it has no values to wrap, provides no methods, and cannot be instantiated. It has only a static TYPE
field containing a reference to the Class
object void.class
. The language has no void
type—void
is a placeholder indicating no return type. The Void
class represents that lack of an actual return type and is only used in reflection (see “The Method Class” on page 420).
The Boolean
class represents the boolean
type as a class. Both the constructor that decodes a string, the valueOf
method and the parseBoolean
method understand "true"
, with any mixture of uppercase and lowercase characters, to be true
. Any other string is interpreted as false
.
The Boolean
class has two static references to objects corresponding to each of the primitive boolean values: Boolean.TRUE
and Boolean.FALSE
.
The Number
class is an abstract class extended by all wrapper classes that represent primitive numeric types: Byte
, Short
, Integer
, Long
, Float
, and Double
.
The abstract methods of Number
return the value of the object converted to any of the numeric types:
public byte byteValue() public short shortValue() public int intValue() public long longValue() public float floatValue() public double doubleValue()
Each extended Number
class overrides these methods to convert its own type to any of the others under the same rules used for an explicit cast. For example, given a Float
object with the value 32.87
, the return value of intValue
on the object would be 32
, just as “(int)32.87
” would be 32
.
The classes Byte
, Short
, Integer
, and Long
extend Number
to represent the corresponding integer types as classes. In addition to the standard Number
methods, each of the integer wrapper classes supports the following methods:
public static
type
parse
Type
(String str, int radix)
Converts the string str
into a numeric value of the specified type
, using the given radix. For example, Integer.parseInt("1010",2)
returns 10, and Integer.parseInt("-1010",2)
returns –10. The characters in the string must all be valid digits for the given radix, except that the first character may be a minus sign to indicate a negative value. A NumberFormatException
is thrown if str
contains any other characters (including leading or trailing whitespace), the value is out of range for this type, or radix
is out of range.
public static
Type
valueOf(String str, int radix)
Returns a wrapper object of class Type
with the value obtained by decoding str
using the specified radix. Note that there are no equivalent constructors with this form. This is equivalent to the two-step process of parsing the string and using that value to construct a new wrapper object. For example, Integer.valueOf("1010",2)
is equivalent to the more verbose expression newInteger(Integer.parseInt("1010",
2))
.
public static
Type
decode(String str)
Returns a wrapper object of class Type
with the value obtained by decoding str
. A leading – character indicates a negative value. The base of the number is encoded in str
: Hexadecimal numbers start with #
, 0x
, or 0X
, while octal numbers are indicated by a leading 0
; otherwise, the number is presumed to be decimal. This is in contrast to the parse
Type
and valueOf
methods, to which you pass the radix as an argument. For example, Long.decode("0xABCD")
returns a Long
with the value 43981, while Long.decode("ABCD")
throws a NumberFormatException
. Conversely, Long.parseLong("0xABCD", 16)
throws a NumberFormatException
, while Long.parseLong("ABCD", 16)
returns a Long
with the value 43981. (The character #
is used in many external data formats for hexadecimal numbers, so it is convenient that decode
understands it.)
For each class, the string-based constructor, parse
Type
(String str)
method, and valueOf
methods work like parse
Type
(String str,
intradix)
, with a radix of 10 if none is specified
In addition, the Integer
and Long
classes each have the following methods, where type
is either int
or long
, respectively:
public static String
toString(
type
val, int radix)
Returns a string representation of the given value in the given radix. If radix is out of range then a radix of 10 is used.
public static String
toBinaryString(
type
val)
Returns a string representation of the two's complement bit pattern of the given value. For positive values this is the same as toString(value,2)
. For negative values the sign of the value is encoded in the bit pattern, not as a leading minus character. For example, Integer.toBinaryString(-10)
returns "11111111111111111111111111110110"
. These string representations for negative values cannot be used with corresponding parse
Type
methods because the magnitude represented by the string will always be greater than MAX_VALUE
for the given type.
public static String
toOctalString(
type
val)
Returns a string representation of the given value in an unsigned base 8 format. For example, Integer.toOctalString(10)
returns "12"
. Negative values are treated as described in toBinaryString
. For example, Integer.toOctalString(-10)
returns "37777777766"
.
public static String
toHexString(
type
val)
Returns a string representation of the given value in an unsigned base 16 format. For example, Integer.toHexString(10)
returns "a"
. Negative values are treated as described in toBinaryString
. For example, Integer.toHexString(-10)
returns "fffffff6"
.
Note that none of the string formats include information regarding the radix in that format—there is no leading 0
for octal, or 0x
for hexadecimal. If radix information is needed then you must construct it yourself.
The Short
, Integer
, and Long
classes have a method reverseBytes
that returns a value with its constituent bytes in the reverse order to the value passed in. For example, Integer.reverseBytes(0x0000ABCD)
returns an int
value with the hexadecimal representation of 0xCDAB0000
. The Integer
and Long
classes also provide a family of bit-querying methods:
public static int
bitCount(
type
val)
Returns the number of one-bits in the two's complement binary representations of val
.
public static
type
highestOneBit(
type
val)
Returns a value consisting of all zero-bits, except for a single one-bit, in the same position as the highest-order (left-most) one-bit in val
.
public static
type
lowestOneBit(
type
val)
Returns a value consisting of all zero-bits, except for a single one-bit, in the same position as the lowest-order (right-most) one-bit in val
.
public static int
numberOfLeadingZeros(
type
val)
Returns the number of zero-bits preceding the highest-order one-bit in val
.
public static int
numberOfTrailingZeros(
type
val)
Returns the number of zero-bits following the lowest-order one-bit in val
.
public static
type
reverse(
type
val)
Returns the value obtained by reversing the order of the bits in val
.
public static
type
rotateLeft(
type
val, int distance)
Returns the value obtained by rotating the bits in val
to the left. In a left rotation the high-order bit moved out on the left becomes the lowest-order bit on the right. Rotating to the left by a negative distance is the same as rotating to the right by a positive distance.
public static
type
rotateRight(
type
val, int distance)
Returns the value obtained by rotating the bits in val
to the right. In a right rotation the low-order bit moved out on the right becomes the highest-order bit on the left. Rotating to the right by a negative distance is the same as rotating to the left by a positive distance.
Finally, the Integer
and Long
classes also define the mathematical signum
function. This function takes a value and returns –1, 0, or +1 as the value is negative, zero, or positive, respectively.
The Float
and Double
classes extend Number
to represent the float
and double
types as classes. With only a few exceptions, the names of the methods and constants are the same for both types. In the following list, the types for the Float
class are shown, but Float
and float
can be changed to Double
and double
, respectively, to get equivalent fields and methods for the Double
class. In addition to the standard Number
methods, Float
and Double
have the following constants and methods:
public final static float
POSITIVE_INFINITY
The value for +∞.
public final static float
NEGATIVE_INFINITY
The value for −∞.
public final static float
NaN
Not-a-Number. This constant gives you a way to get a NaN value, not to test one. Surprising as it may be, NaN==
NaN
is always false because a NaN value, not being a number, is equal to no value, not even itself. To test whether a number is NaN, you must use the isNaN
method.
public static boolean
isNaN(float val)
Returns true
if val
is a Not-a-Number (NaN) value.
public static boolean
isInfinite(float val)
Returns true
if val
is either positive or negative infinity.
public boolean
isNaN()
Returns true
if this object's value is a Not-a-Number (NaN) value.
public boolean
isInfinite()
Returns true
if this object's value is either positive or negative infinity.
In addition to the usual constructor forms, Float
has a constructor that takes a double
argument to use as its initial value after conversion to float
.
Comparison of Float
and Double
objects behaves differently than float
and double
values. Each wrapper class defines a sorting order that treats –0 less than +0, NaNs greater than all values (including +∞), and all NaNs equal to each other.
When converting to a string, NaN values return the string "NaN"
, +∞ returns "Infinity"
and −∞ returns "-Infinity"
. The string-taking constructor, and the parse
Type
method are defined in terms of the valueOf
method, which accepts strings in the following form:
The values "NaN"
or "Infinity"
with an optional leading +
or -
character
A floating-point literal
A hexadecimal floating-point literal
In contrast to the integer wrapper classes, the string is first stripped of leading and trailing whitespace. If the literal forms contain a trailing float or double specifier, such as "1.0f"
, the specifier is ignored and the string is converted directly to a value of the requested type.
To let you manipulate the bits inside a floating-point value's representation, Float
provides methods to get the bit pattern as an int
, as well as a way to convert a bit pattern in an int
to a float
value (according to the appropriate IEEE
754 floating-point bit layout). The Double
class provides equivalent methods to turn a double
value into a long
bit pattern and vice versa:
public static int
floatToIntBits(float val)
Returns the bit representation of the float
value as an int
. All NaN values are always represented by the same bit pattern.
public static int
floatToRawIntBits(float val)
Equivalent to floatToIntBits
except that the actual bit pattern for a NaN is returned, rather than all NaNs being mapped to a single value.
public static float
intBitsToFloat(int bits)
Returns the float
corresponding to the given bit pattern.
The Character
class represents the char
type as a class. It provides methods for determining the type of a character (letter, digit, uppercase, and so forth) and for converting between uppercase and lowercase.
Since a char
is a 16-bit value, and Unicode allows for 21-bit characters, known as code points, many of the methods of Character
are overloaded to take either a char
or an int
that represents an arbitrary code point. Such methods are described in combination below and the pseudo-type codePoint
is used to represent either a char
or an int
code point value.
In addition to MIN_VALUE
and MAX_VALUE
constants, Character
provides the constants MIN_RADIX
and MAX_RADIX
, which are the minimum and maximum radices understood by methods that translate between digit characters and integer values or vice versa,. The radix must be in the range 2–36; digits for values greater than 9 are the letters A
through Z
or their lowercase equivalents. Three methods convert between characters and integer values:
public static int
digit(
codePoint
ch, int radix)
Returns the numeric value of ch
considered as a digit in the given radix. If the radix is not valid or if ch
is not a digit in the radix, –1 is returned. For example, digit('A',16)
returns 10 and digit('9',10)
returns 9, while digit('a',10)
returns –1.
public static int
getNumericValue(
codePoint
ch)
Returns the numeric value of the digit ch
. For example, the character u217F
is the Roman numeral digit M, so getNumericValue('u217F')
returns the value 1000. These numeric values are non-negative. If ch
has no numeric value, –1 is returned; if it has a value but is not a non-negative integer, such as the fractional value ¼
('u00bc'
), getNumericValue
returns –2.
public static char
forDigit(int digit, int radix)
Returns the character value for the specified digit in the specified radix. If the digit is not valid in the radix, the character 'u0000'
is returned. For example, forDigit(10,16)
returns 'a'
while forDigit(16,16)
returns 'u0000'
.
There are three character cases in Unicode: upper, lower, and title. Uppercase and lowercase are familiar to most people. Titlecase distinguishes characters that are made up of multiple components and are written differently when used in titles, where the first letter in a word is traditionally capitalized. For example, in the string "ljepotica"
,[2] the first letter is the lowercase letter lj(u01C9
, a letter in the Extended Latin character set that is used in writing Croatian digraphs). If the word appeared in a book title, and you wanted the first letter of each word to be in uppercase, the correct process would be to use toTitleCase
on the first letter of each word, giving you "Ljepotica"
(using Lj
, which is u01C8
). If you incorrectly used toUpperCase
, you would get the erroneous string "LJepotica"
(using LJ
, which is u01C7
).
All case issues are handled as defined in Unicode. For example, in Georgian, uppercase letters are considered archaic, and translation into uppercase is usually avoided. Therefore, toUpperCase
will not change lowercase Georgian letters to their uppercase equivalents, although toLowerCase
will translate uppercase Georgian letters to lowercase. Because of such complexities, you cannot assume that converting characters to either lower or upper case and then comparing the results will give you a proper case-ignoring comparison. However, the expression
leaves you with a character that you can compare with another similarly constructed character to test for equality ignoring case distinctions. If the two resulting characters are the same, then the original characters were the same except for possible differences in case. The case conversion methods are:
public static
codePoint
toLowerCase(
codePoint
ch)
Returns the lowercase character equivalent of ch
. If there is no lowercase equivalent, ch
is returned.
public static
codePoint
toUpperCase(
codePoint
ch)
Returns the uppercase character equivalent of ch
. If there is no uppercase equivalent, ch
is returned.
public static
codePoint
toTitleCase(
codePoint
ch)
Returns the titlecase character equivalent of ch.
If there is no titlecase equivalent, the result of toUpperCase(ch)
is returned.
The Character
class has many methods to test whether a given character is of a particular type in any Unicode character set (for example, isDigit
recognizes digits in Ethiopic and Khmer). The methods are passed a char
or int
code point and return a boolean
that answers a question. These methods are:
Method | Is the Character… |
---|---|
| a defined Unicode character? |
| a digit? |
| ignorable in any identifier (such as a direction control directive)? |
| an |
| valid to start a source code identifier? |
| valid after the first character of a source code identifier? |
| a letter? |
| a letter or digit? |
| a lowercase letter? |
| a space? |
| a titlecase letter? |
| valid to start a Unicode identifier? |
| valid after the first character of a Unicode identifier? |
| an uppercase letter? |
| a source code whitespace character? |
You can also ask whether a char
value isLowSurrogate
or isHighSurrogate
, a specific int
code point isSupplementaryCodePoint
or isValidCodePoint
, or if a pair of char
values isSurrogatePair
.
Unicode identifiers are defined by the Unicode standard. Unicode identifiers must start with a letter (connecting punctuation such as _
and currency symbols such as ¥
are not letters in Unicode, although they are in the Java programming language) and must contain only letters, connecting punctuation (such as _
), digits, numeric letters (such as Roman numerals), combining marks, nonspacing marks, or ignorable control characters (such as text direction markers).
All these types of characters, and several others, are defined by the Unicode standard. The static method getType
returns an int
that defines a character's Unicode type. The return value is one of the following constants:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Unicode is divided into blocks of related characters. The static nested class Character.Subset
is used to define subsets of the Unicode character set. The static nested class Character.UnicodeBlock
extends Subset
to define a set of standard Unicode character blocks, which are available as static fields of UnicodeBlock
. The static method UnicodeBlock.of
returns the UnicodeBlock
object representing the Unicode character block for a particular character. The UnicodeBlock
class also defines constants for all the blocks, such as GREEK
, KATAKANA
, TELUGU
, and COMBINING_MARKS_FOR_SYMBOLS
. The of
method will return one of these values, or null
if the character is not in any block. For example, the code
tests to see if a character is in the GEOMETRIC_SHAPES
block.
Two Subset
objects define the same Unicode subset if they are the same object, a semantic enforced in Subset
by declaring equals
and hashCode
to be final
, and defining them to have the default Object
behavior for these methods. If you define your own subsets for some reason, you should give people a way analogous to of
to get a single Subset
object for each different kind of Subset
you define.
Working with sequences of characters, whether arrays of char
, strings, or other types that implement CharSequence
(see Chapter 13), is complicated by the fact that supplementary characters need to be encoded as a pair of char
values. To assist with this, the Character
class defines a range of methods that help with the encoding and decoding of surrogate pairs, and accounting for their existence in a sequence of character values:
public static int
charCount(int codePoint)
Returns the number of char
values needed to encode the given code point. This returns 2 for supplementary characters, otherwise 1.
public static int
codePointAt(char[] seq, int index)
Returns the code point defined at the given index in seq
, taking into account that it may be a supplementary character represented by the pair seq[index]
and seq[index+1]
. There is a variant that takes an additional limit
argument that restricts the use of index+1
to be less than a specified value.
public static int
codePointAt(CharSequence seq, int index)
Returns the code point defined at the given index in seq
, taking into account that it may be a supplementary character represented by the pair seq.charAt(index)
and seq.charAt(index+1)
.
public static int
codePointBefore(char[] seq, int index)
Returns the code point defined preceding the given index in seq
, taking into account that it may be a supplementary character represented by the pair seq[index-2]
and seq[index-1]
. There is a variant that takes an additional start
argument, that restricts the use of index-1
and index-2
to be greater than or equal to the specified start position.
public static int
codePointBefore(CharSequence seq, int index)
Returns the code point defined at the given index in seq
, taking into account that it may be a supplementary character represented by the pair seq.charAt(index-2)
and seq.charAt(index-1)
.
public static int
codePointCount(char[] seq, int start, int count)
Returns the number of code points defined in seq[start]
to seq[start+length]
, taking into account surrogate pairs. Any unpaired surrogate values count as one code point each.
public static int
codePointCount(CharSequence seq, int start, int end)
Returns the number of code points defined in seq.charAt(start)
to seq.charAt(end)
, taking into account surrogate pairs. Any unpaired surrogate values count as one code point each.
public static int
offsetByCodePoints(char[] seq, int start, int count, int index, int numberOfCodePoints)
Returns the index into the array, that is numberOfCodePoints
away from index
, considering only the subarray from seq[start]
to seq[start+length]
, taking into account surrogate pairs. This allows you to skip a given number of code points, without having to manually loop through the array, keeping track of surrogate pairs. If any unpaired surrogates are found, they count as one code point.
public static int
offsetByCodePoints(CharSequence seq, int index, int numberOfCodePoints)
Returns the index into the CharSequence
, that is numberOfCodePoints
away from index
, taking into account surrogate pairs.
public static char[]
toChars(int codePoint)
Converts a code point to its UTF
-16 representation as a one- or two-char
array. If codePoint
is not valid, IllegalArgumentException
is thrown.
public static int
toChars(int codePoint, char[] dst, int dstBegin)
Converts a code point to its UTF
-16 representation, storing it in dst
starting at dst[dstBegin]
and returning the number of characters written (either 1 or 2). If codePoint
is not valid, IllegalArgumentException
is thrown.
public static int
toCodePoint(char high, char low)
Converts the given surrogate pair of char
values to their supplementary code point value. This method does not check that high
and low
form a valid surrogate pair, so you must check that yourself by using isSurrogatePair
.
All of these methods that use indices can throw IndexOutOfBoundsException
, if you cause them to try to index outside the given array, or CharSequence
, accounting for any imposed limits on the valid range of indices.
The automatic conversion of a variable of primitive type into an instance of its wrapper class, is termed a boxing conversion—the wrapper object acts like a “box” in which the primitive value is held. The opposite conversion, from an instance of a wrapper class to a primitive value, is termed an unboxing conversion.
A boxing conversion replaces any primitive value v
with a wrapper object of the same value. The wrapper object's type corresponds to the type of v
. For example, given
Integer val = 3;
val
will refer to an Integer
object because 3 is an int
value; val.intValue()
will return the value 3.
An unboxing conversion takes a reference to a wrapper object and extracts its primitive value. Building on the previous example,
int x = val;
is equivalent to the explicit
int x = val.intValue();
and the value of x
is 3. If val
was a Short
reference, the unboxing of val
would invoke val.shortValue()
, and so forth. If a wrapper reference is null
, an unboxing conversion will throw a NullPointerException
.
The boxing and unboxing conversions are applied automatically in many contexts, such as assignment and argument passing, so primitives and reference types can be used almost interchangeably. However, the conversions do not apply everywhere, and in particular you cannot directly dereference a primitive variable, or value, as if it were an object. For example, given the int
variable x
, as above, the expression x.toString()
will not compile. You can, however, apply a cast to the primitive first, such as:
((Object) x).toString()
The exact contexts in which boxing and unboxing automatically occur are discussed in “Type Conversions” on page 216.
Ideally, you would rely on boxing conversions wherever necessary, without giving it a second thought. In practice, you need to be aware that a boxing conversion may need to allocate an instance of a wrapper class, which consumes memory and which may fail if insufficient memory is available. Given that the wrapper classes are immutable, two objects with the same value can be used interchangeably, and there is no need to actually create two distinct objects. This fact is exploited by requiring that boxing conversions for certain value ranges of certain types always yield the same object. Those types and value ranges are:
Type | Range |
---|---|
|
|
| all values |
|
|
|
|
|
|
So given the method
static boolean sameArgs(Integer a, Integer b) { return a == b; }
the following invocation returns true
:
sameArgs(3, 3)
while this invocation returns false
:
sameArgs(3, new Integer(3))
An implementation of the virtual machine may choose to expand on these types and ranges, and is free to determine when instances of the wrapper classes are first created: They could be created eagerly and all stored in a lookup table, or they could be created as needed.
Dare to be naïve. | ||
--R. Buckminster Fuller |
18.227.134.133