Разница между обобщенным типом и wildcard.

 
 
 
Сообщения:29
В чем разница между объявлениями <T> и <?> и <T extends U> и <? extends U>? Я не могу понять этого. В Шилдте приведен пример, в котором нельзя сравнивать <Integer> и <Double>, используя <T>, в то время как <?> позволяет сделать.
 
 
Сообщения:251
Я полагаю вы этот пример имеете ввиду (код немного отрефакторил, но суть осталась та же).
class Stats<T extends Number> {
    T[] nums;
    Stats(T[] o) {
        nums = o;
    }
    double average() {
        double sum = 0.0;
        for (T num : nums) {
            sum += num.doubleValue();
        }
        return sum / nums.length;
    }
    boolean saveAvg(Stats<?> ob) {
        return average() == ob.average();
    }
}

public class WildcardDemo {
    public static void main(String[] args) {
        Integer[] inums = { 1, 2, 3, 4, 5 };
        Stats<Integer> iob = new Stats<>(inums);

        Double[] dnums = { 1.1, 2.2, 3.3, 4.4, 5.5 };
        Stats<Double> dob = new Stats<>(dnums);

        Float[] fnums = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
        Stats<Float> fob = new Stats<>(fnums);

        System.out.println(iob.average());
        System.out.println(dob.average());
        System.out.println(fob.average());

        System.out.println(iob.saveAvg(dob));
        System.out.println(iob.saveAvg(fob));
    }
}


В методе saveAvg мы используем метасимвольный аргумент, который означает неизвестный тип.
saveAvg(Stats<?> ob)

чтобы иметь возможность сравнивать объекты Stats<Integer>, Stats<Double>, Stats<Float> между с собой. Если бы мы использовали
saveAvg(Stats<T> ob)

то объект класса Stats<Integer> могли бы сравнивать только с объектами класса Stats<Integer>.
 
 
Сообщения:251
По поводу <T extends U>, мы указываем, что тип T может быть U или быть унаследован от него.
В примере выше в классе Stats мы указываем, что T гарантированно является класс Number или унаследован от него. Если этого не сделать, то в 9 строчке
sum += num.doubleValue()

мы не сможет вызвать метод doubleValue(). Просто потому что разработчик может тогда вообще передать объект Object в конструктор класса. А у Object метода doubleValue() нет. Чтобы этого не допустить мы ограничиваем тип T сверху до класса Number.
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет