Pull to refresh

Comments 13

Было интересно. +

Я так и не понял, почему они не сделали как в С#, в котором нет type erasure. Я вроде как бы верю, что там были какие-то проблемы с обратной совместимостью, но вот почему там нужна была эта совместимость сама по себе? Почему нельзя было просто дженерики рассматривать как самостоятельный поднабор типов?

хороший вопрос ,не знаю почему задизлайкали , я честно с C# по работе редко встречался , но заметил такую вещь , там есть коллекции с generics и коллекции с примитивами , думаю это было сделано потому что изначально generics не было и архитекторы решили написать новый фрэимворк коллекций с generics и поддерживать старый

Может из-за этого oracle отказались от идея потому что поддерживать две апишки слишком дорого , легче добавить generics в существующие колекции и добавить type erasure чтобы старый код не ломался при переходе на новые версии . Еще есть Project Valhalla , одна из идей переделать Generics чтобы List<Integer> работал с примитивами вместо врапер классов

Потому что С# писался после java и они знали на какие грабли лучше не наступать дважды, а core в java от версии к версии не переписывается, а дописывается.

Т.к. я не копенгаген в Java, хочу заметить, что статья немного неполна без описания, как именно объявлены методы get() и add() в листе. Как компилятор вообще понимает, что get - это чтение, а add - это запись? Для него же метод методу рознь. Там какой-то синтаксис для этого?

Методы get() и add() — это стандартные методы для List, описание их работы выходит за рамки данной статьи. Компилятор никак не понимает, что «get — это чтение, а add — это запись», он просто выполняет логику, реализованную в этих методах. Если переопределить методы, они могут делать всё, что угодно

Понимает по тому, в каком месте стоит определение типа. Если в аргументе - запись, если в возвращаемом значении - чтение. Это не более чем условность для программистов, познающих generic'и. Не самая удачная, на мой взгляд.

И еще, какая у этого всего связь с терминами ковариантность/контравариантность? Похожие вроде вещи. Или это одно и то же? Или одно - подтема другого?

Собственно, ключевое слово extends обеспечивает ковариантность, а super - контравариантность.

Всё потому, что List<Integer> не является потомком от List<Number>, хотя Integer - прямой потомок Number.

Но если есть те, для кого принцип PECS остаётся туманным и непонятным, а упорное гугленье только сгущает «туман»

Как-то странно вы гуглили, вот замечательные видео, где все великолепно объяснено:
youtu.be/_0c9Fd9FacU
youtu.be/MniNZsyjH9E
Если честно, не люблю видеолекции. Мне гораздо проще воспринимать информацию в текстовом виде
public static void someMethod (List<? extends Class3> list) {    
    Class4 class4 = list.get(0); 
}		

"Отсюда неочевидный вывод:" как раз таки очевидный

Допустим Producer Extend работает таким образом и мы можем получить Class4 который наследует Class3. Для примера

public class Class3{

void test(){}

}

public class Class4 extends Class3{

void test2(){}

}

Если мы из листа получили Class4 а в листе изначально был Class3 , у Class3 нету метода test2 , у него есть метод test() и все методы его родителей поэтому extends Class3 может только получить родителя так как компилятор уверен что методы Class3 и всех его родителей будут у объекта который мы получаем

Статье не хватает примера, как это правило применять. Т.е. почему, например, лучше написать поиск максимального элемента массива вот так:
public static <T extends Comparable<? super T>> T max(List<T> list)

а не так:
public static <T extends Comparable<T>> T max(List<T> list)

И, желательно, указать автора этого мнемонического правила
Sign up to leave a comment.

Articles