So lets go through each of them
List <String>myNumbers = new ArrayList<String>();
This is stating that the myNumbers
list will only store Strings
. This compiles because the new ArrayList<String>()
also constraints to 'String` objects only.
Moving on to your second example...
List <String>myNumbers = new ArrayList();
Same as before, the myNumbers
is constraint to only storing String
objects. What is different is that the new ArrayList()
will store any object, it is a raw type. So this compiles. new ArrayList()
will hold String
objects, so it compiles. More can be read about constraints and type reduction this in section 18.2.2 of the Java Language Specifications. This falls under the topic of inference.
Chapter 18. Type Inference
A variety of compile-time analyses require reasoning about types that are not yet known. Principal among these are generic method applicability testing (§18.5.1) and generic method invocation type inference (§18.5.2). In general, we refer to the process of reasoning about unknown types as type inference.
At a high level, type inference can be decomposed into three processes:
- Reduction takes a compatibility assertion about an expression or type, called a constraint formula, and reduces it to a set of bounds on inference variables. Often, a constraint formula reduces to other constraint formulas, which must be recursively reduced. A procedure is followed to identify these additional constraint formulas and, ultimately, to express via a bound set the conditions under which the choices for inferred types would render each constraint formula true.
And finally your third example...
List myNumbers = new ArrayList<String>();
This one is the most interesting one because it introduces type erasure and raw types. Essentially what is happening is that even though the new ArrayList<String>()
is instantiated with the parameterized String
, Java allows for this to be ignored to allow for Raw Types, and the concept and rules of erasure is how it is implemented. At least that is what one can deduce from sections 4.8 and 4.6 of the Java Language Specification.
4.8. Raw Types
To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.
Furthermore...
4.6. Type Erasure
...skipping several bullet points
Type erasure also maps the signature (§8.4.2) of a constructor or method to a
signature that has no parameterized types or type variables. The erasure of a constructor or method signature s is a signature consisting of the same name as s and the erasures of all the formal parameter types given in s.
The return type of a method (§8.4.5) and the type parameters of a generic method or constructor (§8.4.4, §8.8.4) also undergo erasure if the method or constructor's signature is erased.
The erasure of the signature of a generic method has no type parameters.