Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 type generic erasures methods signature and lambdas are not working

The best way to explain this is with the example:

public class Cosmos<T> {
    public void says(Consumer<String> stringConsumer) {
        stringConsumer.accept("we can");
    }
}

I was expecting this would work:

new Cosmos().says(s -> System.out.println(s.length()));

But NO, this is NOT working! Java8 thinks s is an Object!

However, if I define the T with anything, it works:

new Cosmos<Void>().says(s -> System.out.println(s.length()));

How comes the methods signature is related to generic type?

like image 527
igr Avatar asked Feb 04 '23 19:02

igr


1 Answers

The whole concept of raw types was introduced for compatibility with pre-Generics code and consequently, using a raw type will effectively turn Generics off for all uses of this type, whether the generic signatures are related to the type’s declared type parameters or not.

This can be illustrated by the followed code example, which produces a compilation error before Java 5 and continues to produce a compilation error:

ArrayList list = new ArrayList();
String[] str = list.toArray(new String[0]);

in contrast to the generic code

ArrayList<Number> list = new ArrayList<Number>();
String[] str = list.toArray(new String[0]);

which can be compiled without errors, showing that the type parameters of toArray and the List are unrelated (a limitation of the generic type system).

Likewise, when you use new Cosmos(), the result is a raw type and invoking says on it will not use the generic type signature. But you don’t need to specify an actual type:

new Cosmos<>().says(s -> System.out.println(s.length()));

will compile without errors.

like image 153
Holger Avatar answered Feb 07 '23 09:02

Holger