Type Witness in java generics

Some quick answers to your questions:

What is the right way to do this? Using Type Witness or let Java infer?

There is no technical correct answer for this as both approaches are valid. But code readability should always be the quality criterion. So the latter is better. Additionally you might change the type of your arguments at a later point in development. With type inference you do not have to change that line.


Is there a case where using type witness is absolutely needed?

Yes. It is needed when type cannot be inferred from the input arguments to a method. Maybe the generic type is only used for the return value, independently from the types of the arguments. Then you simply must specify it.


Is this a feature from Java 5 or added later?

Generics are a language feature from Java 5 on. Type inference is a compiler feature that is specified in the Java Language Specification (JLS). In the Java 8 JLS this topic got an own chapter. Each Java version did some enhancements in that feature. For example Java 7 introduced the diamond operator. Type witness for methods was already introduced in Java 5 as far as I know.


For completeness, this was added in Java 5. Here are the relevant parts of JLS Third Edition, which covers Java 5 and 6:

8.8.7.1 Explicit Constructor Invocations

ExplicitConstructorInvocation:
    NonWildTypeArgumentsopt this ( ArgumentListopt ) ;
    NonWildTypeArgumentsopt super ( ArgumentListopt ) ;
    Primary. NonWildTypeArgumentsopt super ( ArgumentListopt ) ; 

NonWildTypeArguments:
    < ReferenceTypeList >

ReferenceTypeList: 
    ReferenceType
    ReferenceTypeList , ReferenceType

15.12 Method Invocation Expressions

MethodInvocation:
    MethodName ( ArgumentListopt )
    Primary . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    super . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    ClassName . super . NonWildTypeArgumentsopt Identifier ( ArgumentListopt )
    TypeName . NonWildTypeArguments Identifier ( ArgumentListopt )

Note they are called NonWildTypeArguments. The term "Type Witness" does not appear in the JLS. In JLS SE 8, the invocation specs are rewritten to use the pre-existing notion of TypeArguments; and the word "witness" still appears nowhere.

(MethodName already includes TypeName.Identifier, so that fifth method invocation defines the explicit usage of a Type Witness, which is why it is not marked optional.)


Is there a case where using type witness is absolutely needed?

Is this a feature from Java 5 or added later?

Example below shows mandatory case of using type witness and improvements that came in Java SE 8

Quote from the Generics trail Java documentation:

Suppose you want to invoke the method processStringList with an empty list. In Java SE 7, the following statement does not compile:

processStringList(Collections.emptyList());

The Java SE 7 compiler generates an error message similar to the following:

List<Object> cannot be converted to List<String> The compiler requires

a value for the type argument T so it starts with the value Object. Consequently, the invocation of Collections.emptyList returns a value of type List, which is incompatible with the method processStringList. Thus, in Java SE 7, you must specify the value of the value of the type argument as follows:

processStringList(Collections.<String>emptyList());

This is no longer necessary in Java SE 8. The notion of what is a target type has been expanded to include method arguments, such as the argument to the method processStringList. In this case, processStringList requires an argument of type List. The method Collections.emptyList returns a value of List, so using the target type of List, the compiler infers that the type argument T has a value of String. Thus, in Java SE 8, the following statement compiles:

processStringList(Collections.emptyList());

Tags:

Java

Generics