Edit:
Yes, found the reference. See JLS §15.12.2.1 - Identify Potentially Applicable Methods:
If the method invocation includes explicit type arguments, and the
member is a generic method, then the number of type arguments is equal
to the number of type parameters of the method.
- This clause implies that a non-generic method may be potentially
applicable to an invocation that supplies explicit type arguments.
Indeed, it may turn out to be applicable. In such a case, the type
arguments will simply be ignored.
Emphasis mine.
Also see JLS §15.9.3 - Choosing the Constructor and its Arguments, for understanding how the constructor invocation is resolved. It also mentions that the above mentioned process is followed for resolution.
Original answer:
Such kind of invocation is often required, when you have a generic constructor, and the compiler is not able to infer the correct type arguments. For example, consider the below code:
class Demo<T> {
public <X> Demo(X[] arg1, X arg2) {
// initialization code
System.out.println(arg1.getClass());
System.out.println(arg2.getClass());
}
}
Suppose you invoke that constructor like this:
Demo<String> demo = new Demo<String>(new String[2], new Integer(5));
You would think that the type inference should fail, as the type arguments should have same types. Here we're passing String
and Integer
types. But it doesn't. The compiler infers the type X
as:
Object & Serializable & Comparable<? extends Object&Serializable&Comparable<?>>
Now, you might want the type parameter to be inferred as just Object
, then in that case, you can provide explicit type arguments, as in the below code:
Demo<String> demo = new <Object>Demo<String>(new String[2], new Integer(5));
This is similar to how you give explicit type argument while method invocation.
Now, in your code, you have given the explicit type arguments, but you're using raw type of the class to instantiate it:
ArrayList<Integer> arr = new <String>ArrayList();
The <String>
is the explicit type argument for the constructor, and compiler will be fine with it. But the issue is, you're instantiating raw type ArrayList
, and that is where compiler is giving your unchecked warning. If you change that code to:
ArrayList<Integer> arr = new <String>ArrayList<>();
The warning will go away. But since ArrayList
constructor is not a generic constructor, the type argument seems to be just ignored by the constructor. In fact there is no use of that type argument there.
Strangely enough, this also compiles:
public static void test() { }
public static void main(String... args) {
Main.<Integer>test();
}
...even though test()
is a non-generic method.