Вызываемый метод внутреннего класса generi c не распознает тип generi c - PullRequest
0 голосов
/ 24 марта 2020

Я борюсь со следующим внутренним классом, «наследующим» универсальный c параметр T от внешнего класса. Следующие строки ошибочны:

String string = "string";
new OuterClass<>()
    .inner(string)
    .call(s -> s.length());       // Cannot resolve method 'length' in 'Object'

Минимальный и воспроизводимый пример этих классов:

public class OuterClass<T> {

    public InnerClass<T> inner(T object) {
        return new InnerClass<>(object);
    }

    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    public static final class InnerClass<U> {

        U object;

        public final void call(Consumer<U> consumer) {
            consumer.accept(object);
        }
    }
}

Почему это происходит? Как я должен указать параметр generi c через создание внутреннего класса?

1 Ответ

1 голос
/ 24 марта 2020

По сути, это потому, что вывод типа в <> не учитывает последующие методы, которые вы объединяете в цепочку.

Например, это создает ArrayList<Object>:

new ArrayList<>().add("");

Если я вставлю слово String в <>, IntelliJ не будет жаловаться на то, что слово String является избыточным.

Аналогично, это приводит к ошибке:

OuterClass<String>.InnerClass i = new OuterClass<>().inner(string);

Поскольку с правой стороны выводится OuterClass<Object>.Inner, а с левой стороны - OuterClass<String>.InnerClass.

Чтобы исправить это, необходимо указать параметр generi c:

new OuterClass<String>()
    .inner(string)
    .call(s -> s.length()); 

Что касается вашего редактирования, отредактированный метод inner по-прежнему зависит от универсального c типа Outer, который не может быть правильно выведен.

Вы можете сделать Inner созданный объект не зависит от типа c generi Outer путем добавления другого параметра c generi:

public <U> InnerClass<U> inner(U object) {
    return new InnerClass<>(object);
}
...