Использование объекта в качестве аргумента неограниченного подстановочного объекта ссылки

1

Простой класс:

class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

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

пытается выполнить метод put(), передавая экземпляр объекта Object

Box<?> box = new Box<String>("abc");
box.put(new Object());

Компилятор указывает на ошибку:

The method put(capture#1-of ?) in the type Box<capture#1-of ?> is not applicable for the arguments (Object)

Компилятор на самом деле не знает, какого типа ожидать, но одно можно сказать наверняка - это будет объект или его подкласс. Почему тогда возникает ошибка?

Спасибо

Теги:
generics
unbounded-wildcard

2 ответа

3
Лучший ответ

Ваш пример ясно объясняет, почему.

Фактическим типом окна является Box<String>. Таким образом, вы действительно не хотите, чтобы в это поле помещалось нечто, отличное от экземпляров String.

Box<?> Означает: "поле какого-то типа, неизвестного компилятору". Таким образом, вы можете получить все, что захотите, из такого поля, и вы получите экземпляры объекта, но вы можете ничего не хранить в этом поле, потому что компилятор не может гарантировать, что объект, который вы храните, имеет соответствующий тип:

class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

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

    public T get() {
        return t;
    }
}

Box<?> box = new Box<String>("abc");
Object o = box.get(); // no problem
box.put(new Object()); // fail

Цель генериков - сделать ваш код безопасным. Если вы можете добавить произвольные объекты в поле, которое на самом деле является Box<String>, у вас больше нет безопасности типов.

1

В этом учебнике указано, что:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Same compile time error as yours

"Поскольку мы не знаем, что означает тип элемента c, мы не можем добавлять к нему объекты. Метод add() принимает аргументы типа E, тип элемента коллекции. Когда фактический параметр типа есть?, Он означает какой-либо неизвестный тип. Любой параметр, который мы передаем для добавления, должен быть подтипом этого неизвестного типа. Поскольку мы не знаем, какой тип, мы не можем передать ничего. Единственное исключение - null, которое является членом каждого типа.

С другой стороны, учитывая List, мы можем вызвать get() и использовать результат. Тип результата - неизвестный тип, но мы всегда знаем, что это объект. Поэтому безопасно назначить результат get() переменной типа Object или передать его как параметр, где ожидается тип Object. "

Чтобы объяснить, в основном вы можете вызвать get(), чтобы вернуть тип, но вы не можете добавить, потому что компилятор не знает, какой тип он есть, и передаваемый параметр должен расширять неизвестный тип.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню