2015-03-17 2 views
3

Сегодня я попытался создать reference конструктор. Почему это неправильно?Java 8 - Generic Supplier

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

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

Текст ошибки:

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

Является ли это из-за type erasure? Или, может быть, я делаю это неправильно?

+6

Звонок 'new R();' тоже не работает ... – assylias

+1

Знаете ли вы, что R на момент запуска этого кода? (Подсказка: компилятор этого не делает.) – Seelenvirtuose

ответ

7

Во время компиляции все, что вы знаете о R, является обязательным; что это подтип Collection<Integer>. Вы не знаете, что соответствует классу R. Но вы пытаетесь ссылаться на конструктор - и ссылаться на конструктор, вы должны точно знать, какой класс вы пытаетесь построить. Все перечисленные ниже не будут работать по той же причине: неизвестно, что такое R, и вам нужно знать, что такое R, чтобы вызвать его конструктор.

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

То же самое было бы верно, даже если R были декларирует в качестве <R extends ArrayList<String>>. В этом случае вы знаете, что R расширяет ArrayList<String>, но вы до сих пор не знаете, какой класс!

Если вы пытаетесь получить доступ к виртуальному члену Collection<Integer>, он будет работать:

ToIntFunction<R> sizer = R::size; 

, потому что, независимо от R, оно должно иметь метод size().