UnKnown UnKnown - 2 months ago 14
Java Question

How generics really works as in parameters?

I'm little confused about how the generics works? I'm learning about

function
API in java and there I just test
Function
interface and got confused about
compose
method that how the generics is working in
compose
method.

Reading the generics on the java official tutorial website I realize that if we have any generic type in the method return or parameters we have to declare that type in the signature of method as explained below.

Here is the method I read in official docs tutorial.

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}


Above method have two types, K, V which are declared in the signature after the static keyword as but when I read java
Function
API there is one method called
compose
and the signature of the compose is as

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}


1) The first question where is the T & R declared? which are being used in the return type and in the parameter. Or my understanding is wrong?

Then I read more in generics tutorials and then I try to understand the concept of
super
and
extends
in generics and read here then I test
compose
method more and then confused again about how the
super
and
extends
works in the
compose
method?

public static void main(String... args){
Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);
}


As above I have declared two Function with lamdas. One is having Integer input and String output the other one is reversed from it.

2) The second question is that how
Integer
and
String
are related to
extends
and
super
? There is no relation between
String
and
Integer
class no one is extending each other then how it is working?

I tried my best to explain my question/problem. Let me know what you didn't understand I will try again.

Answer Source

Where are T and R defined?

Remember, compose is declared in the Function interface. It can not only use generic parameters of its own, but also the type's generic parameters. R and T are declared in the interface declaration:

interface Function<T, R> {
    ...
}

What are ? extends and ? super?

? is wildcard. It means that the generic parameter can be anything. extends and super give constraints to the wildcard. ? super V means that whatever ? is, it must be a superclass of V or V itself. ? extends T means that whatever ? is, it must be a subclass of T or T itself.

Now let's look at this:

Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);

From this, we can deduce that T is Integer and R is String. What is V? V must be some type such that the constraints Function<? super V, ? extends T> is satisfied.

We can do this by substituting the argument we passed in - Function<String, Integer> - to get String super V and Integer extends Integer.

The second constraint is satisfied already while the first constraint now says that String must be a super class of V or String itself. String cannot have subclasses so V must be String.

Hence, you can write something like:

Function<String, String> f = one.compose(two);

but not

Function<Integer, String> f = one.compose(two);

When you compose a Function<Integer, String> and a Function<String, Integer> you cannot possibly get a Function<Integer, String>. If you try to do this, V is automatically inferred to be Integer. But String super Integer is not satisfied, so the compilation fails. See the use of the constraints now? It is to avoid programmers writing things that don't make sense. Another use of the constraints is to allow you to do something like this:

Function<A, B> one = ...
Function<C, SubclassOfB> two  = ...
Function<SubclassOfC, B> f = one.compose(two);

There is no relationship between Integer and String in this case, it's all about V.