10

In the Java specification (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9), new has the following form:

ClassInstanceCreationExpression ::=
| new TypeArguments_opt TypeDeclSpecifier TypeArgumentsOrDiamond_opt
    ( ArgumentListopt ) ClassBodyopt
| Primary . new TypeArguments_opt Identifier TypeArgumentsOrDiamond_opt
    ( ArgumentListopt ) ClassBodyopt

What is the purpose of the first optional type argument list after the new? I was not able to find it from my read of section 15.9 (all references to type arguments list seem to refer to the list after the type/identifier). Testing out random bits on the standard Java compiler yields confusing results:

public class Foo<T> { }
// ...
Foo<Integer> t1 = new <Integer> Foo<Integer>();  // works
Foo<Integer> t2 = new <Integer> Foo();           // works -- unchecked warning missing the type arg after Foo
Foo<Integer> t3 = new <Boolean> Foo<Integer>();  // works
Foo<Integer> t4 = new <Float, Boolean> Foo<Integer>();  // works
Foo<Integer> t5 = new <NotDefined> Foo<Integer>();  // fails -- NotDefined is undefined

On theses simple examples, it doesn't seem like this first parameter list does anything meaningful although it parses and checks for the validity of its arguments.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
psosera
  • 165
  • 4

2 Answers2

13

Constructors can declare type parameters too

public class Main {     
    public static class Foo<T> {
        public <E> Foo(T object, E object2) {

        }
    }
    public static void main(String[] args) throws Exception {
        Foo<Integer> foo = new <String> Foo<Integer>(1, "hello");           
    }    
}

That's what the <String> preceding the constructor call is for. It is the type argument for the constructor.

The following

Foo<Integer> foo = new <String> Foo<Integer>(1, new Object());

fails with

The parameterized constructor Foo(Integer, String) of type Main.Foo is not applicable for the arguments (Integer, Object)

In your last

Foo<Integer> t5 = new <NotDefined> Foo<Integer>();  // fails -- NotDefined is undefined

NotDefined is just not a type that is found during compilation. If it was, it would just give you a warning that it is unused.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Excellent. That makes sense. What is still confusing is that you can supply type parameters to a constructor invocation that does not specify any type arguments. What are the rules there? – psosera Sep 08 '13 at 21:58
  • The Eclipse compiler just warns `Unused type arguments for the non generic constructor`. In a similar fashion to methods with type parameters, you don't have to specify the `<...>` if it can be inferred from the type of the argument. – Sotirios Delimanolis Sep 08 '13 at 22:01
  • Ah. Interesting. `javac` doesn't give any warnings (even with -Xlint:warnings on) for it which is likely the root of my confusion. I find it strange that you can "over-specify" type parameters like this (i.e., supply type parameters that the constructor does not use). Regardless, it is what it is, I guess. Thanks! (I assume that the reason why Java allows this is related to generic type erasure. If anyone else can fill in the details, that would be great!) – psosera Sep 08 '13 at 22:05
3

You can add useless type arguments for method invocations, weird stuff like

Math.<Runnable>max(1,2);

System.out.<Button>println();

see http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1-200-E

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.

This rule stems from issues of compatibility and principles of substitutability. Since interfaces or superclasses may be generified independently of their subtypes, we may override a generic method with a non-generic one. However, the overriding (non-generic) method must be applicable to calls to the generic method, including calls that explicitly pass type arguments. Otherwise the subtype would not be substitutable for its generified supertype.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61