Java Tutorials - Herong's Tutorial Examples - Version 7.03, by Dr. Herong Yang
Type Argument Inference by Return Value
This section provides a tutorial example on type argument inference by return value. The compiler will deduce the type argument by looking at the context where the return value is used. if the type parameter is not used in the method argument list.
As described earlier, if type argument is not specified explicitly when invoking a generic method, the compiler will perform the type argument inference process. It will look at method argument list first to deduce the type argument, if the type parameter is used in there. If not, the compiler will look at the return value do the job.
Here is another tutorial example to show you how the compiler uses the return value to deduce the argument type:
/* TypeInferenceByReturnValue.java - Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ class TypeInferenceByReturnValue { public static <T> T alias(Object o) { return (T) o; } public static void main(String[] a) { String s = "1234"; /* Test 1 - Type argument specified as String */ String as = TypeInferenceByReturnValue.<String>alias(s); System.out.println("Alias: "+as); /* Test 2 - Type argument inferred to String by looking at the assignment operation String bs = TypeInferenceByReturnValue.alias(s); System.out.println("Alias: "+bs); */ /* Test 3 - Type argument inferred to String by looking at the invocation context Object ao = "Hello "+TypeInferenceByReturnValue.alias(s); System.out.println("Alias: "+ao); /* Test 4 - Type argument inferred to Long but runtime exception occurred Long al = TypeInferenceByReturnValue.alias(s); System.out.println("Alias: "+al); */ /* Test 5 - Type argument inferred to Short but runtime exception occurred Number an = (Short) TypeInferenceByReturnValue.alias(s); System.out.println("Alias: "+an); */ /* Test 6 - Type argument inferred to Object: but failed to compile the entire statement Integer ai = Integer.valueOf(TypeInferenceByReturnValue.alias(s)); System.out.println("Alias: "+ai); */ } }
On test 1, I was not using type argument inference. So there was no compilation issue except an "unchecked" warning at the (return (T) o;) statement. See the result below:
C:\herong>javac TypeInferenceByReturnvalue.java Note: TypeInferenceByReturnvalue.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. C:\herong>java TypeInferenceByReturnValue Alias: 1234
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" by looking at the left side of the assignment operation. See the result below:
Alias: 1234 Alias: 1234
On test 3, the compiler also did a good job to deduce the type argument to be "String" by looking at the expected type of the string concatenation operation. See the result below:
Alias: 1234 Alias: Hello 1234
On test 4, the compiler did an ok job and deduced the type argument to be "Long" by looking at the left side of the assignment operation. But this caused a runtime ClassCastException:
Alias: 1234 Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long at TypeInferenceByReturnValue.main(TypeInferenceByReturnvalue.java:30)
On test 5, the compiler did an ok job and deduced the type argument to be "Short" by looking at the cast operation on the return value. But this caused a runtime ClassCastException:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Short at TypeInferenceByReturnValue.main(TypeInferenceByReturnvalue.java:36)
On test 6, the compiler in JDK 1.7 failed to deduce the type argument to a type that can meet the requirement of Integer.valueOf(). It used the default type, "Object", as the type argument, leading to a compilation error on Integer.valueOf():
TypeInferenceByReturnvalue.java:44: error: no suitable method found for valueOf(Object) = Integer.valueOf(TypeInferenceByReturnValue.alias(s)); ^ method Integer.valueOf(int) is not applicable (actual argument Object cannot be converted to int by method invocation conversion) method Integer.valueOf(String) is not applicable (actual argument Object cannot be converted to String by method invocation conversion) method Integer.valueOf(String,int) is not applicable (actual and formal argument lists differ in length)
However, the compiler in JDK 1.8 is not generating any errors on test 6. It returns expected result of "Alias: 1234".
If you want to see more examples of using generic methods and type argument inference, see 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