Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does this Java function infer its generic type from?

Tags:

java

generics

I found a bit of generic code and it has stumped me as to how it actually works. I don't understand where it gets the generic type that is used for T. This is an oversimplified example but I still don't understand how this is valid Java code.

public static void main(String[] args) {
  System.out.print(get());
}

public static <T> T get()
{
  return (T) getObj();
}

public static Object getObj() 
{
  return Boolean.FALSE;
}
like image 798
Deadron Avatar asked Jan 10 '13 16:01

Deadron


People also ask

Where is generic used in Java?

Generics should be used instead of raw types ( Collection< T > instead of Collection , Callable< T > instead of Callable , …) or Object to guarantee type safety, define clear type constraints on the contracts and algorithms, and significantly ease the code maintenance and refactoring.

What is generic function in Java?

Generic Method: Generic Java method takes a parameter and returns some value after performing a task. It is exactly like a normal function, however, a generic method has type parameters that are cited by actual type. This allows the generic method to be used in a more general way.

How do you find the type of generic class?

You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass. of(String. class) .

What is Java type inference?

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable.

What is type inference in Java generics?

Java Generics - Type Inference. Type inference represents the Java compiler's ability to look at a method invocation and its corresponding declaration to check and determine the type argument(s). The inference algorithm checks the types of the arguments and, if available, assigned type is returned.

What are generic methods in Java?

Generic Methods introduced you to type inference, which enables you to invoke a generic method as you would an ordinary method, without specifying a type between angle brackets. Consider the following example, BoxDemo, which requires the Box class:

How does the compiler infer the type of a generic class?

The compiler infers the type String for the formal type parameter, T, of the constructor of this generic class (because the actual parameter of this constructor is a String object). Compilers from releases prior to Java SE 7 are able to infer the actual type parameters of generic constructors, similar to generic methods.

How do you invoke a generic class in C++?

An invocation of a generic type is generally known as a parameterized type. To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis: Box<Integer> integerBox = new Box<Integer> ();


2 Answers

Type inference happens based on the callsite.

However, type inference only applies to return types if the return value is assigned to a variable. This is written in the spec

If the method result occurs in a context where it will be subject to assignment conversion, then [...]

Otherwise, any unresolved type parameters always become Object.
In your example, that will work, because there is a print(Object) overload.

On the other hand, look at this code:

print(get());

public void print(Boolean x) { }

public <T> T get() {
    return (T) Boolean.FALSE;
}

This will give a compilation error, because the compiler infers get() as returning Object before looking at print().

like image 78
SLaks Avatar answered Jan 28 '23 15:01

SLaks


In the code you wrote T is not bound to anything. Java will assign a type to T whenever you invoke the get method and it will look at the type that you are expecting to get back... but that seems to be working only if you declare explicitly which type are you waiting for. Look at the following example:

public static void jump(String a) {
}

public static <T> T get() {
    return (T) null;
}

public static void main(String[] args) {
    //This works quite well, generic parameter T is inferred to be String
    String blah = get();
    jump(blah);
}

On the other hand

public static void jump(String a) {
}

public static <T> T get() {
    return (T) null;
}

public static void main(String[] args) {
    //This doesn't work, Java does not bind T to anything hence Object is used... and no jump for object is found
    jump(get());
}

At least this is how it works on Java 6.

like image 45
Claudio Avatar answered Jan 28 '23 13:01

Claudio