Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 - Generic Supplier

Today I tried to reference a constructor in generic. Why is it incorrect?

import java.util.Collection;
import java.util.function.Supplier;

class Foo<R extends Collection<Integer>> {
    Supplier<R> supplier = R::new;  // Compiler error!
}

Error text:

java: unexpected type
  required: class or array
  found:    type parameter R

Is it because of type erasure? Or maybe I'm doing it wrong?

like image 760
naXa Avatar asked Mar 17 '15 14:03

naXa


1 Answers

At compile time, all you know about R is its bound; that it is a subtype of Collection<Integer>. You don't know what class R corresponds to. But you are trying to reference a constructor -- and to reference a constructor, you have to know exactly what class you're trying to construct. All of the following would fail to work for the same reason: it is not known what R is, and you need to know what R is to call its constructor.

Supplier<R> supplier = R::new
Supplier<R> supplier = () -> new R();
R r = new R();

The same would be true even if R were declares as <R extends ArrayList<String>>. In this case, you'd know that R extends ArrayList<String>, but you still don't know what class it is!

If you were trying to access a virtual member of Collection<Integer>, it would work:

ToIntFunction<R> sizer = R::size;

because, whatever R is, it must have a size() method.

like image 160
Brian Goetz Avatar answered Sep 23 '22 21:09

Brian Goetz