Java Generics в массовом порядке отличается от шаблонов C ++.
В основном в C ++ шаблоны в основном представляют собой прославленный набор препроцессоров / макросов ( Примечание: , поскольку некоторые люди, похоже, не в состоянии понять аналогию, я не говорю, что обработка шаблонов - это макрос). В Java они в основном являются синтаксическим сахаром для минимизации шаблонного преобразования объектов. Вот довольно приличное введение в шаблоны C ++ против обобщений Java .
Чтобы уточнить этот момент: когда вы используете шаблон C ++, вы в основном создаете другую копию кода, как если бы вы использовали макрос #define
. Это позволяет вам делать такие вещи, как int
параметры в определениях шаблонов, которые определяют размеры массивов и тому подобное.
Java не работает так. В Java все объекты имеют экстент от java.lang.Object , поэтому, прежде чем использовать Generics, вы должны написать код, подобный следующему:
public class PhoneNumbers {
private Map phoneNumbers = new HashMap();
public String getPhoneNumber(String name) {
return (String)phoneNumbers.get(name);
}
...
}
потому что все типы коллекций Java использовали Object в качестве базового типа, чтобы вы могли помещать в них что угодно. Java 5 катится и добавляет дженерики, чтобы вы могли делать такие вещи, как:
public class PhoneNumbers {
private Map<String, String> phoneNumbers = new HashMap<String, String>();
public String getPhoneNumber(String name) {
return phoneNumbers.get(name);
}
...
}
И это все, что Java Generics: обертки для приведения объектов. Это потому, что Java Generics не улучшены. Они используют стирание типа. Это решение было принято, потому что Java Generics появился настолько поздно, что они не хотели нарушать обратную совместимость (Map<String, String>
можно использовать всякий раз, когда требуется Map
). Сравните это с .Net / C #, где стирание типов не используется, что приводит ко всем видам различий (например, вы можете использовать примитивные типы, а IEnumerable
и IEnumerable<T>
не имеют никакого отношения друг к другу).
И класс, использующий дженерики, скомпилированные с помощью компилятора Java 5+, можно использовать в JDK 1.4 (при условии, что он не использует никаких других функций или классов, требующих Java 5+).
Вот почему Java Generics называют синтаксическим сахаром .
Но это решение о том, как сделать дженерики, имеет настолько глубокие последствия, что (10) FAQ по обобщению Java *1036* возникло, чтобы ответить на многие, многие вопросы о Generics Java.
Шаблоны C ++ имеют ряд функций, которых нет в Generics Java:
Использование аргументов примитивного типа.
Например:
template<class T, int i>
class Matrix {
int T[i][i];
...
}
Java не позволяет использовать аргументы примитивного типа в обобщениях.
Использование аргументов типа по умолчанию , который мне не хватает в Java, но для этого есть причины обратной совместимости;
- Java позволяет ограничивать аргументы.
Например:
public class ObservableList<T extends List> {
...
}
Действительно нужно подчеркнуть, что вызовы шаблонов с разными аргументами действительно являются разными типами. Они даже не разделяют статических членов. В Java это не так.
Помимо различий с обобщениями, для полноты приведем базовое сравнение C ++ и Java (и еще одно ).
И я также могу предложить Мышление на Java . Как программист на C ++, многие понятия, такие как объекты, уже будут второй натурой, но есть небольшие различия, поэтому может быть целесообразно иметь вводный текст, даже если вы просматриваете части.
Многое из того, что вы узнаете при изучении Java, - это все библиотеки (обе стандартные - то, что входит в JDK - и нестандартные, которые включают в себя обычно используемые вещи, такие как Spring). Синтаксис Java более многословен, чем синтаксис C ++, и не имеет большого количества функций C ++ (например, перегрузка операторов, множественное наследование, механизм деструктора и т. Д.), Но это не делает его строго подмножеством C ++.