What are all of the different kinds of type casting in Java and what do they mean?
Type casting conversions are covered in Section 5.5 of the JLS. See the JLS for all of the gory details.
There are five (5) categories of legal type casting conversions: identity conversion, narrowing and widening primitive conversions, narrowing and widening reference conversions. There's also a category of "forbidden" conversions.
Note also that there are implicit conversions which are applied in to the expressions in assignments (aka "assignment conversion") and to the actual arguments in method invocations (aka "method invocation conversion"). Assignment conversion is covered in Sections 5.2 and 15.26 of the JLS and method invocation conversion is covered in Sections 5.3, 15.9, and 15.12 of the JLS.
The forbidden conversions... In general, primitive types cannot
have their values casted to a reference type and, conversely, reference
types cannot have their values casted to a primitive type. The
null type cannot be converted to/from any primitive type.
Array types may not be converted to each other unless their base types are
convertible to each other. Arrays can't be converted to a class type other
type can only be converted to
boolean and to
String and nothing else can be converted to
boolean except itself. For the exhaustive list, see section
5.1.7 of the JLS.
String casting is simple... You can't do
it. Yes, it's true that all types, including
null, can be
String but you may not cast
anything to the
String type (with the single exception of the
identity conversion). This is covered in Sections 5.1.6 and 5.4 of the
Identity conversion is also simple. You can convert anything to the
same type as itself. I.e.,
this may seem silly, it's an important base case which allows for things
like redundant casts.
Primitive types can have their values cast to other primitive types via identity conversion or narrowing or widening primitive conversions. A key point to note is that, by definition, neither narrowing nor widening primitive conversions will generate run-time exceptions.
Narrowing primitive conversion is the conversion of a larger type to a
smaller type. I.e.,
byte. Given that the
smaller type cannot represent all of the possible values of the larger
type, narrowing primitive conversions may lose information. For example,
narrowing of integral types is performed by discarding all but the number
of lowest order bits which will fit into the target type. See Section
5.1.3 of the JLS for rest of the conversion details.
Widening primitive conversion is the conversion of a smaller primitive
type to a larger primtive type. I.e.,
long. Widening of integral types to other integral types and
double are precise and lose no
numeric value information. Widening conversions from integral types to
floating point types may result in a loss of precision due to the nature of
floating point representations. See Section 5.1.2 of the JLS for the rest
of the details.
Reference types can have their values cast to other reference types
via identity conversion or narrowing or widening conversions and a special
conversion of the
null type to any reference type.
A quick aside on alternative nomenclature... A good number of people use the terms "upcasting" and "downcasting" when talking about type casting references. Their notion of "up" and "down" relate to their view of class hierarchies being drawn with the root class at the top and the subclasses drawn successively lower. [They also call them inheritance trees even though they've drawn the tree upside down. :-)] In that model, "upcasting" is equivalent to a "widening reference conversion" and "downcasting" is equivalent to a "narrowing reference conversion." Due to the potential confusion, I recommend that you refrain from using the "upcasting" and "downcasting" terminology.
A narrowing reference conversion is the conversion of a reference to a
given type to a reference of another type which is more restrictive and
type compatible. I.e.,
Integer is a sub-class of Number). Similarly, you can cast a
super-interface to any of it's sub-interfaces. You can cast
Object references to any class, interface, or array type. See
Section 5.1.5 of the JLS for comprehensive coverage.
Note very clearly that narrowing reference conversions require a
run-time test to make sure that the actual reference object is allowed to
be referenced by the narrowed typed reference. If it's not then the
run-time system will throw a
ClassCastException. You may, of
course, use the
instanceof operator to check that yourself.
A widening reference conversion is the conversion of a reference to a
given type to a reference of another type which is less restrictive and
type compatible. I.e.,
Integer is a sub-class of Number). Similarly, you may cast a sub-interface
to any of its super-interfaces. Also, you may cast a class to any of the
interfaces which it implements. Any class or interface reference to the
Object type. Casts are also allowed from
any class, interface, or array type. For the full list, read Section 5.1.4
of the JLS.
Note that widening reference conversions require only a source compile-time check for correctness and therefore they do not throw any sort of run-time exception.