The first example is type safe meaning if you attempt to add anything other than a String object into myNumbers list then you'll get a compiler error.
List myNumbers = new ArrayList();
The second example is also type-safe, the compiler will ensure only objects of type String are stored in myNumbers list.
List myNumbers = new ArrayList();
Raw Types
A raw type is the name of a generic class or interface without any
type arguments.
When generics were introduced in JDK 1.5, the raw types were retained only for backwards compatibility with older versions of java. Though using raw types is still permissible, you should avoid them for the reasons below:
- typically raw types require casts
- raw types are NOT type safe and some important kinds of errors will only appear at runtime.
- raw types are less expressive & don't self-document in the same way as parameterized types.
The last example is a raw type meaning we can add all type of objects into myNumbers list, However, you should avoid them when you can.
List myNumbers = new ArrayList();
note - if you do not specify the type, as shown above, every item within myNumbers list is treated as a type Object.
Where to specify type parameter on ArrayList?
From the examples you've shown this is the preferred way:
List myNumbers = new ArrayList();
However, you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (< >) as long as the compiler can infer the type arguments from the context.
meaning instead of this:
List myNumbers = new ArrayList();
we can do this:
List myNumbers = new ArrayList<>();