Что хорошего в дженериках, зачем их использовать? - PullRequest
79 голосов
/ 17 сентября 2008

Я подумала, что предложу этот софтбол тому, кто захочет выбить его из парка. Что такое дженерики, каковы преимущества дженериков, почему, где, как я должен их использовать? Пожалуйста, оставьте это довольно простым. Спасибо.

Ответы [ 28 ]

1 голос
/ 17 сентября 2008

В итоге, дженерики позволяют вам более точно указать, что вы собираетесь делать (более строгая типизация).

Это имеет несколько преимуществ для вас:

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

  • Это также дает вам более ранние отзывы о правильности вашей программы. Вещи, которые ранее не работали во время выполнения (например, из-за того, что объект не мог быть приведен в желаемом типе), теперь терпят неудачу во время компиляции, и вы можете исправить ошибку до того, как ваш отдел тестирования отправит отчет о проблемах.

  • Компилятор может выполнять больше оптимизаций, например избегать бокса и т. Д.

1 голос
/ 17 сентября 2008

Единственная причина, по которой они обеспечивают Тип безопасности

List<Customer> custCollection = new List<Customer>;

в отличие от

object[] custCollection = new object[] { cust1, cust2 };

в качестве простого примера.

1 голос
/ 17 сентября 2008

Еще одним преимуществом использования Generics (особенно с коллекциями / списками) является то, что вы получаете проверку типов времени компиляции. Это действительно полезно при использовании общего списка вместо списка объектов.

1 голос
/ 29 июня 2018

Очевидные преимущества, такие как «безопасность типов» и «отсутствие кастинга», уже упоминались, поэтому, возможно, я могу рассказать о некоторых других «преимуществах», которые, я надеюсь, помогут.

Прежде всего, дженерики - это независимая от языка концепция, и, IMO, это может иметь больше смысла, если вы одновременно думаете о регулярном (во время выполнения) полиморфизме.

Например, полиморфизм, как мы знаем из объектно-ориентированного проектирования, имеет понятие времени выполнения, в котором объект вызывающего объекта определяется во время выполнения по мере выполнения программы, и соответствующий метод вызывается соответствующим образом в зависимости от типа времени выполнения. В общем, идея несколько похожа, но все происходит во время компиляции. Что это значит и как вы этим пользуетесь?

(Давайте придерживаться универсальных методов, чтобы сохранить его компактность) Это означает, что вы все еще можете использовать один и тот же метод в отдельных классах (как вы делали ранее в полиморфных классах), но на этот раз они автоматически генерируются компилятором, зависит от типы, установленные во время компиляции. Вы настраиваете ваши методы на тип, который вы даете во время компиляции. Таким образом, вместо того, чтобы писать методы с нуля для каждого типа , который есть у вас, как при полиморфизме во время выполнения (переопределение метода), вы позволяете компилятору выполнять работу во время компиляции. Это имеет очевидное преимущество, поскольку вам не нужно выводить все возможные типы, которые могут использоваться в вашей системе, что делает ее гораздо более масштабируемой без изменения кода.

Классы работают примерно так же. Вы параметризуете тип, и код генерируется компилятором.

Как только вы получите представление о «времени компиляции», вы можете использовать «ограниченные» типы и ограничивать то, что может передаваться как параметризованный тип через классы / методы. Таким образом, вы можете контролировать то, что будет проходить, что является мощной вещью, особенно если вы используете фреймворк для других людей.

public interface Foo<T extends MyObject> extends Hoo<T>{
    ...
}

Никто не может установить что-либо, кроме MyObject.

Кроме того, вы можете «навязывать» ограничения типа для аргументов вашего метода, что означает, что вы можете убедиться, что оба аргумента метода будут зависеть от одного и того же типа.

public <T extends MyObject> foo(T t1, T t2){
    ...
}   

Надеюсь, все это имеет смысл.

1 голос
/ 17 сентября 2008

Обобщения позволяют вам создавать объекты со строгой типизацией, но вам не нужно определять конкретный тип. Я думаю, что лучший полезный пример - это List и подобные классы.

Используя общий список, вы можете иметь любой список List List, и вы всегда можете сослаться на строгую типизацию, вам не нужно конвертировать или что-либо подобное с Array или стандартным List.

0 голосов
/ 05 июня 2009

Использование дженериков для коллекций просто и понятно. Даже если вы используете его повсюду, выигрыш от коллекций для меня - победа.

List<Stuff> stuffList = getStuff();
for(Stuff stuff : stuffList) {
    stuff.do();
}

против

List stuffList = getStuff();
Iterator i = stuffList.iterator();
while(i.hasNext()) {
    Stuff stuff = (Stuff)i.next();
    stuff.do();
}

или

List stuffList = getStuff();
for(int i = 0; i < stuffList.size(); i++) {
    Stuff stuff = (Stuff)stuffList.get(i);
    stuff.do();
}

Одно это стоит предельной «стоимости» дженериков, и вам не нужно быть универсальным Гуру, чтобы использовать это и получить ценность.

0 голосов
/ 17 сентября 2008

Я однажды выступил с докладом на эту тему. Вы можете найти мои слайды, код и аудиозапись на http://www.adventuresinsoftware.com/generics/.

0 голосов
/ 05 июня 2009

Обобщения также дают вам возможность создавать более повторно используемые объекты / методы, в то же время обеспечивая поддержку для конкретных типов. Вы также получаете большую производительность в некоторых случаях. Я не знаю полной спецификации Java Generics, но в .NET я могу указать ограничения для параметра Type, например, «Реализует интерфейс», «Конструктор» и «Деривация».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...