Changes the type of an expression.
The cast operator (often simply called cast) changes or
specifies the type of an expression, throwing a ClassCastException
if its argument cannot be coerced to the specified type.
Casts can be used to perform certain automatic conversions, broaden or shrink the type of an expression, change the type being instantiated by a lambda or method reference, clarify ambiguous method invocations, and more.
Cast Operators are used in cast expressions. Cast expressions can be written in the following forms:
1 | ( primitive-type )
primitive-castable-expression |
2 | ( reference-type )
reference-castable-expression |
2 | ( reference-type interface-type-list ) reference-castable-expression |
where...
primitive-type | is any one of the types: boolean , byte ,
short , char , int , long ,
float , or double .
|
primitive-castable-expression | is an expression of one of the following types:
Other types are syntactically, but not semantically permitted. Syntactically, a primitive-castable-expression can also be any one of the following expressions, but a primitive-type–cast may only be applied to a type convertible to a primitive type, and none of the following types can be converted to a primitive type through a single cast.
|
reference-type | is any non-primitive type. This can be either a user-defined type
(class , interface including @interface ,
or enum ), a type parameter variable, or any array type
(including one with a primitive component type).
|
reference-castable-expression | is an expression of one of the following types:
|
interface-type-list | is a sequence that specifies additional types, each of which must
be an interface type. Each element of the sequence is
comprised of the & token (used as a separator between
the types specified) followed by the type itself. Each type in the
sequence must be an interface .
|
1 A normal cast to a primitive type.
2 A normal cast to a reference type.
3 An intersection cast. Intersection casts always use reference types.
Every expression has a type which is known at compile time.Every expression is classified as either a standalone or a poly expression. A standalone expression's type can be determined from its contents whereas a poly expression's type can be determined from its context. Casting can have runtime effects, but is usually used to change the type of an expression without changing the value, which is a compile-time operation; using the cast operator on some expression forms a new expression whose type is that specified in the cast.
A cast expression can affect the runtime value of its operand. Notable cases include the case that the operand is a lambda expression or method reference expression and the case that either the operand or the type being casted to is primitive.
Casting operates on its argument by performing a casting conversion. A casting conversion is the attempted change of a value's type to the type specified by the cast.
All primitive types can be cast between each other except for the type
boolean
, which cannot be cast to or from any other
primitive type (since it is not numeric).
Widening primitive conversion is performed when an expression of a
smaller numeric primitive type is cast to a larger numeric primitive
type, such as in casting an int
expression to type long
,
or a short
to type double
.
For integral (non-decimal) types, the value resulting from a widening
cast conversion always exactly represents the original value, except
when casting a negative byte
to type char
(see byte
--> char
).
Integral numeric types are ordered by size as follows:
byte
< short
< int
< long
char
is equal in byte-size to short
,
but is unsigned.
If any such smaller type is cast to a larger type, the conversion will
occur without loss of information and the larger-type value will
exactly represent the same as the smaller-type value. This is because
a larger such type can represent all of the values that the smaller
such type can (e.g. any byte
value is also a valid int
value).
A cast of a value from a smaller such type to a larger such type performs a two's-complement sign-extension on the binary data of the value (extending the sign bit) to fill the bits of the larger type.
Converting a char
to a wider integral type (i.e., to int
or long
) involves a zero-extension of the value (i.e.,
bits introduced by the larger type are set to 0). Therefore, casting
from char
to int
or long
never
changes the value being cast.
float
-->
double
Conversion of a float
to type double
results
in a double
value that represents the exact same number as
the original float
value.
Converting an integral-type value to a floating point type performs
IEEE 754 rounding with round-to-nearest mode. The resulting floating
point number is the representable value that is nearest to the source
value, with ties between two potential floating point numbers being
broken by picking the one whose least significant bit is zero (i.e.,
the one that is farthest from 0
).
Conversion from byte
, short
, or char
to float
will always result in a float
that
exactly represents the same number as the original value. Conversion
from byte
, short
, char
, or int
to double
will result in a double
that
exactly represents the same number as the source value.
Conversion of large integral types to floating point types, i.e.
int
or long
converted to float
,
orlong
converted to double
,undergoes IEEE 754 rounding with round-to-nearest mode to arrive at a floating point value.
double
to float
conversion performs IEEE 754
rounding. Infinity
values and NaN
are
preserved. That is, casting NaN
or positive or negative Infinity
from double
to float
results in the exact
same value, but of type float
.
Integral-type values, when cast to a smaller integral type, lose their
most significant bits so as to fit into the smaller integral type. All
signed integral types (byte
, short
, int
,
and long
) use the most-significant bit (leftmost bit) to
negativity, and the remaining bits to represent value. The unsigned char
type uses all its bits to represent value. This can cause the sign to
change when casting a larger integral type to a smaller integral type,
including in the case of casting from char
to byte
,
where the result may be negative despite no possible char
value being negative.
Conversion of a floating point to an integral value rounds the floating
point number to the nearest integer value, picking the integer closest
to zero if two integers are equidistant to the original floating point
value, unless the floating point value is NaN
in which
case the result of the cast conversion is 0
, of type
specified by the cast.
A check is then made to determine if the integer value obtained is a valid:
long
if the target type of the cast is long
,
orint
, if the target type of the cast is another
integral primitive type.
In either case, if the rounded integer value is a valid element, it is
the result of the cast expression (if casting to long
or int
),
or the value is converted from int
to the smaller,
integral, primitive type via primitive integral
narrowing conversion.
If the rounded integer value is not a valid element, then the closest
valid long
(if casting to long
) or int
(otherwise) is used. This is maintained in the case that the floating
point value is positive or negative Infinity
, in which
case the integer value is either the maximum or minimum value for the long
(if casting to long
) or int
(otherwise) type.
If the cast is to a type other than long
or int
then the int
min- or max-value is converted to the target
type of the cast via primitive integral
narrowing conversion.
In this way, floating point values are only directly converted to
either long
or int
, even when cast to short
,
char
, or byte
, but for these cases, an
additional conversion is made from int
to the target type
being cast to.
byte
--> char
Conversion of a byte
into a char
will operate
in two steps:
byte
to int
,
int
to char
.
Casting can induce boxing, which is a conversion that results in an
object (whose type is one of the wrapper types Byte
, Short
,
Character
, Integer
, Long
, Float
,
Double
, or Boolean
, each a member of the java.lang
package) that represents the primitive value being cast. Wrapper types
and boxing are useful for generics, as generic program elements cannot
be parameterized with a primitive type (e.g. List<int>
is not allowed, whereas List<Integer>
is).
An expression of any primitive type, can be cast to that primitive type's wrapper type. That is, an expression can cast be from type:
byte
to Byte
,short
to Short
,char
to Character
,int
to Integer
,long
to Long
,float
to Float
,double
to Double
, andboolean
to Boolean
.
In addition to these casts, a primitive type expression can be cast to
any supertype of the primitive type's wrapper type, including generic
types or intersection types. For example, Integer
implements Comparable<Integer>
and so a primitive
type int
expression can be cast to Comparable<Integer>
or even to intersection type Number &
Comparable<Integer>
.
The result of casting a primitive-type value to a reference type so that it is boxed is an instance of the primitive type's corresponding wrapper type that represents the primitive value that was boxed. When invoked on the result of a boxing conversion, the following methods,
booleanValue()
for Boolean
,byteValue()
for Byte
,shortValue()
for Short
,charValue()
for Character
,intValue()
for Integer
,doubleValue()
for Double
, andfloatValue()
for Float
will return the primitive value that was boxed, unless the value was NaN
,
in which case the isNaN()
method for Double
and Float
will return true
.
The values:
-128
to 127
for int
(inclusive),
0
to 127
for char
(inclusive), and
true
and false
for boolean
,are cached so that boxing one of the values repeatedly results in the same object.
If any of these values is boxed twice, an identity comparison (with the==
operator) of the results of the
two boxings always returns true
. For example: Object a = 10, b = 5 + 5;
System.out.println(a == b);
will always print
true
Unboxing occurs when an expression of reference type is cast to an
expression of primitive type. The cast operates by first attempting to
narrow the reference type to the appropriate wrapper type; (the wrapper
type that corresponds to the primitive type being cast to), then the
cast returns a primitive type with the same value as the one
represented by the value being cast (or the cast throws a NullPointerException
at runtime if the reference type's value is null
).
If the type of the expression being cast (primitive-castable-expression),
is not a supertype of the wrapper type that corresponds to primitive-type (i.e., the wrapper type
that corresponds to the cast's target type), the cast expression raises
a compile-time error. For example, trying to cast an expression of type
List
to type int
raises a compile-time error
because the List
expression can never evaluate to an Integer
object.
If the cast is valid at compile-time but, at runtime, the actual value
of the primitive-castable-expression
is not an instance of the wrapper type, a ClassCastException
is raised. If primitive-castable-expression
evaluates to null
, the cast results in a NullPointerException
.
If the cast succeeds, the resulting primitive value is exactly the same
as the value represented by the object that was cast. In particular,
the cast is the same as the result of the corresponding value
method of the wrapper type.
Casting a reference type expression to a supertype of the expression's type never results in a compile-time error and always succeeds. Casting to a supertype can be used to change which method or constructor is invoked by a method invocation expression, or can be used to change the type of value that a lambda expression evaluates to.
Narrowing reference conversions always perform a run-time check to
verify that the actual value that reference-castable-expression
evaluates to is an instance of the reference-type
(or intersection type) being cast to. If the value is not an instance,
the cast fails with a ClassCastException
.
A cast that performs a narrowing reference conversion can convert a reference-castable-expression:
Object
to String
),
final
type to a non-parameterized interface
type that reference-castable-expression's
type does not implement or extend,
java.lang.Cloneable
or java.io.Serializable
to any array type (since arrays always implement Cloneable
and Serializable
),
A
to another array
type with component B
where A
can be
converted to B
via a narrowing reference conversion.
It is always permissible to cast an expression to its own type.
Casting to a primitive type is treated different, syntactically, from casting to a reference type. To avoid syntactical ambiguity and ease parsing, a cast to one or more reference types cannot be applied to a unary plus or minus expression, or to a pre-increment or pre-decrement expression. This restriction holds even in the case when an intersection cast is used, (despite the lack of syntactic ambiguity with an intersection cast).
The operand to a cast expression can be a poly expression (although, whether the argument is a poly expression is dependent on what kind of expression the argument is specify how).
If the argument for a cast expression is a poly expression, the target type for the poly expression is exactly the type specified by the cast, unless that specified type is generic and contains any wildcard type arguments, in which case the target type is instead the original type with each wildcard replaced with a concrete type through capture-conversion
The actual type of a poly expression is based on the type of expression the poly expression is and on the target type of the context that the poly expression is used in.In this case, the cast expression's type is still exactly the type specified in the cast operator's parentheses, but the target type for the cast expression's argument will have no wildcards. See Poly Expressions & Wildcard Casts for details. This allows otherwise impossible lambda expressions (see below).
Casting a poly expression to a generic type with a wildcard type parameter causes the poly expression's finalized type to be different from the type of the cast.
Consider some generic interface
:
interface Example<T> {
void doSomething(T input);
}
The type parameter declaration <T>
does not declare
an explicit bound, so its bound is Object
(as if declared
as <T extends Object>
). Instances can be obtained
using lambda expressions:
Object ex = (Example<?>) a -> System.out.println(a);
// ex is an instance of Example
Due to the rules of casting with poly
expressions as arguments, the lambda expression is created as an
instance of Example<Object>
, with Object
used as the type argument rather than the wildcard ?
(since wildcards are not allowed to be specified as type arguments for
the instantiation of a type).
Expressions of type Example<Object>
can be assigned
to expressions of type Example<?>
, due to subtyping
rules, so the thus Example<?>
-type lambda
expression is permitted as the argument of the cast, and the full cast
expression maintains its type, Example<?>
.
This allows lambda expressions and method reference expressions to be cast to a type possessing wildcard type arguments without the need to first cast the expression to a type without wildcard arguments.
Casting to a supertype may be used on an argument to a method invocation expression to change which method is invoked by the expression.
class Test {
void m(String x) { System.out.println("String"); }
void m(Object x) { System.out.println("Object"); }
void example() {
m("abc"); // Invokes m(String) which prints "String"
m((Object) "abc"); // Invokes m(Object) which prints "Object"
}
}
In both cases, the same value ("abc"
) is passed to the
methods, but which method is called is determined by the type of the
expression used as an argument, not the type of the value used as an
argument.
Serializable
, Cloneable
, & Arrays
The type of every dimension of a multidimensional array, possibly
except for the last dimension's type, is an instance of java.lang.Cloneable
and of java.io.Serializable
(and an instance of Object
,
which is the supertype of Cloneable
and of Serializable
),
and so an expression of either type (or of type Object
)
can be cast to any array type:
Object a = null;
System.out.println((Object[]) a); // An array of objects is also an object.
System.out.println((int[]) a); // An array of primitive-type values is also an object.
System.out.println((String[][][][][][]) a); // A multi-dimensional array is also an object.
Output:
null
null
null
Each of the above casts performs narrowing reference conversion,
attempting to convert from a supertype (Object
) to a
subtype (some array).
+
or -
cannot be cast to a reference type, but can be cast to a primitive
type. This simplifies the Java grammar but seems to be the result of a
nominal oversight in the language's design. The justification for this grammar seems to be an oversight in
the design of the Java language. The relevant
footnote, in section 15.15, assumes that
all type names involved in casts on numeric values are known keywords
However, there are in fact valid reference-type casts, generic casts, and even intersection casts that can be applied to other expressions of numeric types, though none to the aforementioned unary expressions:
// Valid
System.out.println((Object) 1);
System.out.println((Comparable<Integer>) 1);
System.out.println((Object & Serializable & Comparable<Integer>) 1);
// Invalid
// System.out.println((Object) -1);
// System.out.println((Comparable<Integer>) -1);
// System.out.println((Object & Serializable & Comparable<Integer>) -1);
For example,
System.out.println((int) +10); // Valid
// System.out.println((Integer) +10); // Invalid
int x = 10;
System.out.println((int) ++x); // Valid
// System.out.println((Integer) ++x); // Invalid
This limitation can be overcome by parenthesizing the argument to the cast expression.
System.out.println((Integer) (+10)); // Valid
int x = 10;
System.out.println((Integer) (++x)); // Valid
interface
in a way that is otherwise
impossible without using raw types.
An interface
can be declared generic with a type
parameter bounded by a private (inaccessible) class. For example:
class ContainerType {
private static class PrivateClass { }
public interface Interface<T extends PrivateClass> {
int doSomething();
}
}
Classes outside of ContainerType
can refer to Interface
but not use it as a type unless using it raw or with the ?
wildcard type argument. The only other permissible parameterization
is PrivateClass
which is inaccessible.
In a separate class, one can instantiate Interface
using
a lambda expression or method reference without using Interface
as a raw type and without having to refer to PrivateClass
(which would raise a compile-time error) using a wildcard:
public class Example {
public static void main(String[] args) {
Object x = (Interface<?>) () -> 1;
}
}
Because of the cast, the lambda expression is instantiated as the
type Interface<PrivateClass>
due to capture conversion. This becomes
the type of the lambda expression itself. Since PrivateClass
is not explicitly referenced, no compile-time error occurs. The cast
expression converts the type to Interface<?>
,
which is the result of the cast expression itself.