Java Tutorials - Herong's Tutorial Examples - Version 7.03, by Dr. Herong Yang
Type Argument Inference by Parameter List
This section provides a tutorial example on type argument inference by parameter list. The compiler will deduce the type argument by looking at actual arguments for the method parameter list if the type parameter is used there.
Type argument inference (also called type inference) on generic method invocation is something I will not recommend. But if you want to use it, you can gain some experience with the following tutorial example:
/* TypeInferenceByParameter.java - Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ class TypeInferenceByParameter { public static <T extends Comparable<T>> T maxGeneric(T a, T b) { if (a.compareTo(b)>=0) { return a; } else { return b; } } public static void main(String[] a) { String as = "1234"; String bs = "789"; Integer ai = new Integer(1234); Long bl = new Long(789L); /* Test 1 - Type argument specified as String */ String ms = TypeInferenceByParameter.<String>maxGeneric(as, bs); System.out.println("Maximum: "+ms); /* Test 2 - Type argument inferred to String by looking at parameters as and bs Object os = TypeInferenceByParameter.maxGeneric(as, bs); System.out.println("Maximum: "+os); */ /* Test 3 - Type argument inference failed to deduce to a single type Long ml = TypeInferenceByParameter.maxGeneric(ai, bl); System.out.println("Maximum: "+ml); */ /* Test 4 - Type argument inference failed to deduce to a subtype of Comparable Integer mi = TypeInferenceByParameter.maxGeneric( (Number)ai, (Number)bl); System.out.println("Maximum: "+mi); */ /* Test 5 - Type argument inferred to Short but runtime exception occurred Number mn = TypeInferenceByParameter.maxGeneric( (Short)(Number)ai, (Short)(Number)bl); System.out.println("Maximum: "+mn); */ } }
On test 1, I was not using type argument inference. So there was no compilation error and runtime exception. The execution result was correct:
Maximum: 789
On test 2, I let the compiler to do the type inference. The compiler did a good job to deduce the type argument to be "String" and the result was correct:
Maximum: 789 Maximum: 789
On test 3, I purposely provided inconsistent types in the argument list "ai, bl". The JDK 1.7 compiler failed on the type inference process and gives me this compilation error. The error message said that the inferred type was INT#1 and did not conform to the declared bound. But I see the root cause is that found types "Integer,Long" does not match required types "T,T" where both of types must be the same type:
TypeInferenceByParameter.java:31: error: method maxGeneric in class TypeInferenceByParameter cannot be applied to given types; Long ml = TypeInferenceByParameter.maxGeneric(ai, bl); ^ required: T,T found: Integer,Long reason: inferred type does not conform to declared bound(s) inferred: INT#1 bound(s): Comparable<INT#1> where T is a type-variable: T extends Comparable<T> declared in method <T>maxGeneric(T,T) where INT#1,INT#2 are intersection types: INT#1 extends Number,Comparable<? extends INT#2> INT#2 extends Number,Comparable<?>
In the JDK 1.8, the compilation error message on test 3 is better:
TypeInferenceByParameter.java:31: error: method maxGeneric in class TypeInferenceByParameter cannot be applied to given types; Long ml = TypeInferenceByParameter.maxGeneric(ai, bl); ^ required: T,T found: Integer,Long reason: inference variable T has incompatible bounds equality constraints: Integer,Long lower bounds: Long,Integer where T is a type-variable: T extends Comparable<T> declared in method <T>maxGeneric(T,T) 1 error
On test 4, I did provide the consistent types "Number,Number". But "Number" is not a subtype of "Comparable". So the compiler failed again with the appropriate message saying that inferred type is "Number" and does not conform to the declared bound.
TypeInferenceByParameter.java:37: error: method maxGeneric in class TypeInferenceByParameter cannot be applied to given types; Integer mi = TypeInferenceByParameter.maxGeneric( ^ required: T,T found: Number,Number reason: inferred type does not conform to upper bound(s) inferred: Number upper bound(s): Comparable<Number> where T is a type-variable: T extends Comparable<T> declared in method <T>maxGeneric(T,T) 1 error
On test 5, I double-casted both parameter objects to be the same type "Short". The compiler was stupid and deduced the type argument to be "Short" with no errors. But the runtime caught the type casting issue and gave a "ClassCastException".
Maximum: 789 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Short at TypeInferenceByParameter.main(TypeInferenceByParameter.java:44)
I think we have done enough testing with type argument inference with the method parameter list. We will test type argument inference with the method return value in the next section.
Last update: 2014.
Table of Contents
Execution Process, Entry Point, Input and Output
Primitive Data Types and Literals
Bits, Bytes, Bitwise and Shift Operations
Managing Bit Strings in Byte Arrays
Reference Data Types and Variables
StringBuffer - The String Buffer Class
System Properties and Runtime Object Methods
Generic Classes and Parameterized Types
►Generic Methods and Type Inference
Comparing Generic Method with Non-Generic Method
Non-Generic Method Example - maxNonGeneric()
Generic Method Example - maxGeneric()
Generic Methods in java.util.Collections Class
Testing Generic Methods in Collections Class
What Is Type Argument Inference?
►Type Argument Inference by Parameter List
Type Argument Inference by Return Value
Generic Methods using Parameterized Types
Parameterized Type as Generic Method Return Type
Lambda Expressions and Method References
Execution Threads and Multi-Threading Java Programs
ThreadGroup Class and "system" ThreadGroup Tree
Synchronization Technique and Synchronized Code Blocks
Deadlock Condition Example Programs