11

I understand what Type Witness is as I see from Generics Trail In Java Documentation

BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);

Alternatively, if you omit the type witness,a Java compiler automatically infers (from the method's arguments) that the type parameter is Integer:

BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

Would like to understand

  • What is the right way to do this? Using Type Witness or let Java infer?
  • Is there a case where using type witness is absolutely needed?
  • Is this a feature from Java 5 or added later?
Abhijit Mazumder
  • 8,641
  • 7
  • 36
  • 44

3 Answers3

15

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.

Alex Martian
  • 3,423
  • 7
  • 36
  • 71
Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • can you give me an example of the second point from java source or any standard open source code? I know this too much to ask but just checking :) – Abhijit Mazumder Jul 24 '14 at 13:51
  • @AbhijitMazumder I do not know of such an example. The only thing I could do is construct such an example, but maybe you could do that, too. – Seelenvirtuose Jul 24 '14 at 14:50
  • +1 for *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, indipendently from the types of the arguments. Then you simply must specify it.* – Mahesha999 Mar 08 '15 at 21:06
4

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());
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Alex Amorales
  • 323
  • 3
  • 9
2

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.)

Ken
  • 814
  • 4
  • 3