Java 7 Diamond Операция в вызове метода

Это своего рода дополнительный вопрос к обсуждению:

Почему оператор Diamond не работает в вызове addAll() в Java 7?

Из учебника по Java,

http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html

Обратите внимание, что ромб часто работает в вызовах методов; однако для большей ясности предлагается использовать ромб в первую очередь для инициализации переменной, в которой он объявлен

Итак, я немного запутался в первой строке. Когда работает алмаз в вызовах методов?

Немного больше объяснения о том, как работает алмазный оператор, можно найти здесь:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html?

И из этого я попробовал следующее, которое отлично работает:

Дай что у меня есть:

private static class Box<T>{
    public Box(T t){}
}
static void f(Box<Integer> box){}

вызов вроде следующего компилируется нормально:

f(new Box<>(new Integer(10)));

Параметр типа при вызове конструктора в вызове метода f() выше выводится из аргумента в конструктор (т.е. Integer).

Так это то, что подразумевается, когда учебник говорит

Обратите внимание, что алмаз часто работает в вызовах методов

Если нет, может ли кто-нибудь любезно привести пример, в котором алмаз работает в вызове метода?

3 ответа

Так это то, что подразумевается, когда учебник говорит

Я думаю, что да, хотя есть несколько ошибок, когда дело доходит до <> операторы.

В вашем случае инстанцирование Box не является проблемой, учитывая, что тип может быть тривиально выведен с помощью аргумента конструктора. Попробуйте изменить конструктор, чтобы "не" взять в Integer или же T и посмотрите, как не удается вызвать.

class BadBox<T> {

    private T t;

    public BadBox(){}    

    public void setT(T t) {
        this.t = t;
    }

    static void f(BadBox<Integer> box){}

    public static void main(final String[] args) {
        f(new BadBox<>());  //fails, should have worked ideally
    }    
}

Точно так же посмотрите на этот класс:

class Testi<R> {    
    public void doIt(Set<? extends R> sets) {
    }

    public static void main(final String[] args) {
            // works since type inference is now possible
        new Testi<CharSequence>().doIt(new HashSet<>(Arrays.asList("a")));

            // fails; nothing which can help with type inference
        new Testi<CharSequence>().doIt(new HashSet<>();
    }       
}

Точно так же проблема в вашем связанном вопросе (относительно addAll) может быть просто решена, помогая компилятору немного следующим образом:

List<String> list = new ArrayList<>();
list.add("A");

// works now! use only if you love diamond operator ;)
list.addAll(new ArrayList<>(Arrays.asList(new String[0])));
// or the old-school way
list.addAll(new ArrayList<String>()));

Алмазные операторы также, кажется, ломаются, когда дело доходит до реализации анонимных классов следующим образом:

final String[] strings = { "a", "b", "c" };
Arrays.sort(strings, new Comparator<>() {
    @Override
    public int compare(String o1, String o2) {
        return 0;
    }
});

К счастью, в этом случае компилятор довольно явно упоминает, что <> не работает / не работает с анонимными классами.

Я не думаю, что стоит думать о том, когда это работает, а когда нет. Компилятор скажет вам, и поэтому вы должны переписать то, что не работает.

За этим нет реального обоснования; это скорее похоже на то, что разработчики поместили текущие ограничения реализации фактического компилятора в конкретное время в спецификации и сказали нам: так оно и должно быть.

Java 8 снимает многие из этих ограничений без адской заморозки. Например

Arrays.asList("foo", "bar").addAll(new ArrayList<>());

компилируется с Java 8 без ошибок. И почему бы нет?

Дело не в вызове метода. Автономное заявление

new Box<>(new Integer(10));

также компилирует. Есть достаточно информации, чтобы сделать вывод T за Box (т.е. из аргумента Integer)

С другой стороны, это не компилируется

new ArrayList<>();

Нет никакого способа узнать, какой список желателен.

Collection<String> strings = new ArrayList<>();

это работает, потому что вывод помогает тип цели Collection<String>

Другие вопросы по тегам