java tutorial - Руководство Java Generics - учебник java - java programming - учиться java - java basics - java for beginners
1- Почему Java Generics?
- Generics это понятие, введенное в Java, начиная с версии 5. Перед тем, как ознакомить вас с понятием Generics, посмотрим на код Java перед версией 5.
- В данном примере, ArrayList это списко, вы можете добавить., удалить, изменить в списке, и иметь доступ к элементам в списке.
BeforeJ5Example.java
package org.wikitechy.tutorial.generics;
import java.util.ArrayList;
public class BeforeJ5Example {
public static void main(String[] args) {
// Создать объект ArrayList (Список).
// Чтобы содержать имена пользователей.
ArrayList userNames = new ArrayList();
// Добавить String в список.
userNames.add("tom");
userNames.add("jerry");
// Вы случайно добавляете элемент не String вида в список.
// (Это вполне позволено).
userNames.add(new Integer(100));
// И получить первый элемент
// Он является Object (Но вы знаете, что он является String)
// ==> tom
Object obj1 = userNames.get(0);
// Сделать cast в String.
String userName1 = (String) obj1;
System.out.println("userName1 = " + userName1);
// Получить элемент 2.
// (Вы знаете, что он является String)
// ==> jerry
String userName2 = (String) userNames.get(1);
System.out.println("userName2 = " + userName2);
// Получить 3-ий элемент и сделать cast чтобы он стал String.
// (На самом деле он является Integer).
// (Ошибка cast происходит здесь).
String userName3 = (String) userNames.get(2);
System.out.println("userName3 = " + userName3);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаСитуация в Java перед версией 5:
- Вам нужно создать объект ArrayList с целью хранения только элементов вида String, при этом добавить в этот список элемент не вида String где-нибудь в программе (Это вполне возможно), когда вы получаете эти элементы и приводите к виду String, выбрасывается исключение.TODO (Image)
- Java 5 вводит понятие Generics. С помощью Generics, вы можете создать объект ArrayList который позволяет содержать только объекты вида String, и не позволяет иметь другие виды объектов.
J5Example.java
package org.wikitechy.tutorial.generics;
import java.util.ArrayList;
public class J5Example {
public static void main(String[] args) {
// Создать ArrayList (Список)
// Этот список только позволяет содержать элементы вида String.
ArrayList<String> userNames = new ArrayList<String>();
// Добавить String в список.
userNames.add("tom");
userNames.add("jerry");
// Вы не можете добавить элементы не String вида в список.
// (Ошибка при компиляции).
userNames.add(new Integer(100)); // Compile Error!
// Вам не нужно делать cast элемента.
String userName1 = userNames.get(0);
System.out.println("userName1 = " + userName1);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда
java - джава - учиться java - учебник java -
Пример J5
- примеры java - java-программы
- Когда вы создаете объект ArrayList <String>, он содержить только элементы вида String, компилятор Java не позволяет этому объекту содержать элементы отличающиеся от String.
2- ВидGeneric для Class & Interface
2.1- Generics Class
- ример ниже определяет class generics. KeyValueэто class generics который содержит пару ключей/значения (key/value).
KeyValue.java
package org.wikitechy.tutorial.generics.ci;
public class KeyValue<K, V> {
private K key;
private V value;
public KeyValue(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- K, V в class KeyValue
называется параметорм generics, который является определенной ссылкой. При использовании этого class-а вам нужно определить точный параметр. - Смотрите пример использования class KeyValue.
KeyValueDemo.java
package org.wikitechy.tutorial.generics.ci;
public class KeyValueDemo {
public static void main(String[] args) {
// Создать объект KeyValue
// Integer: Номер телефона (K = Integer)
// String: Имя пользователя. (V = String).
KeyValue<Integer, String> entry = new KeyValue<Integer, String>(12000111, "Tom");
// Java понимает вид возврата как Integer (K = Integer).
Integer phone = entry.getKey();
// Java понимает вид возврата как String (V = String).
String name = entry.getValue();
System.out.println("Phone = " + phone + " / name = " + name);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаЗапуск примера:

java - джава - учиться java - учебник java -
значение ключа демо
- примеры java - java-программы
2.2- Наследование класса Generics
- Сlass расширенный из class generics, может определить вид параметра generics, сохранить параметры generics или добавить параметры generics.
Пример 1:
PhoneNameEntry.java
package org.wikitechy.tutorial.generics.ci;
// Этот класс расширенный (extends) из класса KeyValue<K,V>.
// И ясно определяет K,V:
// K = Integer (Номер телефона).
// V = String (Имя пользователя).
public class PhoneNameEntry extends KeyValue<Integer, String> {
public PhoneNameEntry(Integer key, String value) {
super(key, value);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаПример использования PhoneNameEntry:
package org.wikitechy.tutorial.generics.ci;
public class PhoneNameEntryDemo {
public static void main(String[] args) {
PhoneNameEntry entry = new PhoneNameEntry(12000111, "Tom");
// Java понимает вид возврата как Integer.
Integer phone = entry.getKey();
// Java понимает вид возврата как String.
String name = entry.getValue();
System.out.println("Phone = " + phone + " / name = " + name);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаПример 2:
StringAndValueEntry.java
package org.wikitechy.tutorial.generics.ci;
// Этот класс расширен (extends) из класса KeyValue<K,V>.
// Ясно определить вид параметра <K> как String.
// Сохранить вид параметра Generic <V>.
public class StringAndValueEntry<V> extends KeyValue<String, V> {
public StringAndValueEntry(String key, V value) {
super(key, value);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаПример использования StringAndValueEntry class:
package org.wikitechy.tutorial.generics.ci;
public class StringAndValueEntryDemo {
public static void main(String[] args) {
// (Код сотрудника, Имя сотрудника).
// V = String (Имя сотрудника)
StringAndValueEntry<String> entry = new StringAndValueEntry<String>("E001", "Tom");
String empNumber = entry.getKey();
String empName = entry.getValue();
System.out.println("Emp Number = " + empNumber);
System.out.println("Emp Name = " + empName);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаПример 3:
package org.wikitechy.tutorial.generics.ci;
// Этот класс расширен (extends) из класса KeyValue<K,V>
// Он имеет еще один параметр Generics <I>.
public class KeyValueInfo<K, V, I> extends KeyValue<K, V> {
private I info;
public KeyValueInfo(K key, V value) {
super(key, value);
}
public KeyValueInfo(K key, V value, I info) {
super(key, value);
this.info = info;
}
public I getInfo() {
return info;
}
public void setInfo(I info) {
this.info = info;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда2.3- Generics Interface
- Интерфейс с параметром Generics:
GenericInterface.java
package org.wikitechy.tutorial.generics.ci;
public interface GenericInterface<G> {
public G doSomething();
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Пример class-а, применяющего интерфейс:
GenericInterfaceImpl.java
package org.wikitechy.tutorial.generics.ci;
public class GenericInterfaceImpl<G> implements GenericInterface<G>{
private G something;
@Override
public G doSomething() {
return something;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Пример class-а, применяющего интерфейс:
GenericInterfaceImpl.java
package org.wikitechy.tutorial.generics.ci;
public class GenericInterfaceImpl<G> implements GenericInterface<G>{
private G something;
@Override
public G doSomething() {
return something;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда2.4- Java не поддерживает Generics Throwable
- Вы не можете создать class generic который является наследником Throwable, java не поддерживет создание такого class-а

java - джава - учиться java - учебник java -
универсальный класс исключения
- примеры java - java-программы
- Сообщение ошибки компилятора:
- Java не поддерживает создание class-а Throwable generic, так как это не приносит никакую пользу. Причиной является информация Generic только используется компилятором для управления кодом программиста. В процессе запуска Java информация Generic не существует, объект Mistake
или Mistake являются объектом Mistake.
} catch( Mistake<Account> ea) {
// Если происходит исключение Mistake, данный блок будет выполнен.
...
} catch( Mistake<User> eu) {
// Данный блок никогда не выполняется
...
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда3- Методы generics
- Метод в class или интерфейсе, который может стать generic (generify).
MyUtils.java
package org.wikitechy.tutorial.generics.m;
import java.util.ArrayList;
import org.wikitechy.tutorial.generics.ci.KeyValue;
public class MyUtils {
// <K,V> : Говорит этот метод имеет 2 вида параметра K,V
// Метод возвращает объект вида K.
public static <K, V> K getKey(KeyValue<K, V> entry) {
K key = entry.getKey();
return key;
}
// <K,V> : Говорит этот метод имеет 2 вида параметра K,V
// Метод возвращает объект вида V.
public static <K, V> V getValue(KeyValue<K, V> entry) {
V value = entry.getValue();
return value;
}
// ArrayList<E>: Список содержит элемент вида E.
// Метод возвращает объект вида E.
public static <E> E getFirstElement(ArrayList<E> list) {
if (list == null || list.isEmpty()) {
return null;
}
E first = list.get(0);
return first;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Например, используя метод generics:
MyUtilsDemo.java
package org.wikitechy.tutorial.generics.m;
import java.util.ArrayList;
import org.wikitechy.tutorial.generics.ci.KeyValue;
public class MyUtilsDemo {
public static void main(String[] args) {
// K = Integer: Phone
// V = String: Name
KeyValue<Integer, String> entry1 = new KeyValue<Integer, String>(12000111, "Tom");
KeyValue<Integer, String> entry2 = new KeyValue<Integer, String>(12000112, "Jerry");
// (K = Integer).
Integer phone = MyUtils.getKey(entry1);
System.out.println("Phone = " + phone);
// Список содержит элементы вида KeyValue<Integer,String>.
ArrayList<KeyValue<Integer, String>> list = new ArrayList<KeyValue<Integer, String>>();
// Добавить элемент в список.
list.add(entry1);
list.add(entry2);
KeyValue<Integer, String> firstEntry = MyUtils.getFirstElement(list);
System.out.println("Value = " + firstEntry.getValue());
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаMyUtilsDemo.java
package org.wikitechy.tutorial.generics.m;
import java.util.ArrayList;
import org.wikitechy.tutorial.generics.ci.KeyValue;
public class MyUtilsDemo {
public static void main(String[] args) {
// K = Integer: Phone
// V = String: Name
KeyValue<Integer, String> entry1 = new KeyValue<Integer, String>(12000111, "Tom");
KeyValue<Integer, String> entry2 = new KeyValue<Integer, String>(12000112, "Jerry");
// (K = Integer).
Integer phone = MyUtils.getKey(entry1);
System.out.println("Phone = " + phone);
// Список содержит элементы вида KeyValue<Integer,String>.
ArrayList<KeyValue<Integer, String>> list = new ArrayList<KeyValue<Integer, String>>();
// Добавить элемент в список.
list.add(entry1);
list.add(entry2);
KeyValue<Integer, String> firstEntry = MyUtils.getFirstElement(list);
System.out.println("Value = " + firstEntry.getValue());
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда4- Инициализация объекта Generic
- Иногда вы хотите инициировать объект Generic:
// Создать объект Generic.
T t = new T(); // Error
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаИнициализация объекта generic, как выше не позволено, так как <T> не существует в момент запуска Java. Он имеет значение только для компилятора, управляющего кодом программиста. Все виды <T> похожи друг на друга и понимаются как Object в момент запуска Java.
Для инициализации объекта generic <T> вам нужно предоставить Java объект Class<T>, Java создаст объект <T> в момент запуска используя Java Reflection.
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаBar.java
package org.wikitechy.tutorial.generics.o;
import java.util.Date;
public class Bar {
// Этот класс должен иметь Constructor (конструктор) по умолчанию .
public Bar() {
}
public void currentDate() {
System.out.println("Now is: " + new Date());
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаMyGeneric.java
package org.wikitechy.tutorial.generics.o;
public class MyGeneric<T> {
private T tobject;
public MyGeneric(Class<T> tclass)
throws InstantiationException, IllegalAccessException {
this.tobject = (T) tclass.newInstance();
}
public T getTObject() {
return this.tobject;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаMyGenericDemo.java
package org.wikitechy.tutorial.generics.o;
public class MyGenericDemo {
public static void main(String[] args) throws Exception {
MyGeneric<Bar> mg = new MyGeneric<Bar>(Bar.class);
Bar bar = mg.getTObject();
bar.currentDate();
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда5- Массив Generic
- Вы можете объявить массив generic, но вы не можете создать массив generic.
// Вы можете объявить массив generic.
T[] myarray;
// Но не можете инициализировать массив generic.
// (Это не разрешено).
T[] myarray = new T[5]; // Error!
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаПример:
GenericArray.java
package org.wikitechy.tutorial.generics.a;
public class GenericArray<T> {
private T[] array;
// Contructor.
public GenericArray(T[] array) {
this.array = array;
}
public T[] getArray() {
return array;
}
// Возвращает последний элемент массива.
public T getLastElement() {
if (this.array == null || this.array.length == 0) {
return null;
}
return this.array[this.array.length - 1];
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаGenericArrayDemo.java
package org.wikitechy.tutorial.generics.a;
public class GenericArrayDemo {
public static void main(String[] args) {
// Массив String.
String[] names = new String[] { "Tom", "Jerry" };
GenericArray<String> gArray = new GenericArray<String>(names);
String last = gArray.getLastElement();
System.out.println("Last Element = " + last);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Возвращаясь к вопросу, почему Java не поддерживает инициализацию массива Generic:
// Почему Java не поддерживает инициализировать массив Generic?
T[] genericArray = new T[10]; // Error!
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Это потому что вид generic не существует в момент запуска, List
или List это List. Generic только работает с компиляторами для управления кодом программиста. Это означает, что компилятору Java нужно знать точно, что такое для компиляции (compile) new T[10];. Если не знает точно, то по умолчанию считает T как Object. Тогда:
// Допустим Java позволяет инициализировать массив Generic:
T[] tarray = new T[10];
// Во время компиляции (Compile-time)
// компилятор будет считать <T> как Object.
// Команда выше индентична:
T[] tarray = new Object[10];
// Если во время запуска приложения, вы определяете <T> как String.
// Значит:
String[] tarray = new Object[10];
// Пункт выше не разрешен. Причина:
// Type mismatch: cannot convert from Object[] to String[]
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Если вы хотите инициализировать массив Generic вам нужно передать Java объект Class
, помогая Java создать массив generic в момент запуска используя Java Reflection. Смотрите изображенный пример:
GArray.java
package org.wikitechy.tutorial.generics.a;
import java.lang.reflect.Array;
public class GArray<T> {
private Class<T> tclass;
private T[] myArray;
public GArray(Class<T> tclass) {
this.tclass = tclass;
final int size = 10;
myArray = (T[]) Array.newInstance(tclass, size);
}
public T[] getMyArray() {
return this.myArray;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаGArrayDemo.java
package org.wikitechy.tutorial.generics.a;
public class GArrayDemo {
public static void main(String[] args) {
GArray<Integer> garray = new GArray<Integer>(Integer.class);
Integer[] myArray = garray.getMyArray();
myArray[0] = 1;
myArray[2] = 0;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда6- Generics с Wildcards
- В коде Generic, знак вопроса (?), называется wildcard, который представляет неопределенный вид. Вид параметра wildcard (wildcard parameterized type) это случай вида Generic, там где минимум один параметр является wildcard.
- Пример вида параметра wildcard (wildcard parameterized) :
- Collection
- List extends Number>
- Comparator super String>
- PairString.
- Wildcard могут использованы в разныъ ситуациях: как вид параметра, поле (field), или локальная переменная; иногда как возвратный вид (Будет объяснено в практических примерах). Wildcard никогда не использованы как аргумент для вызова метода Generic, создания объекта class generic, или супертип (supertype).
- Wildcard находящиеся в разных позициях имеют разные значения:
- Collection denotes all instantiations of the Collection interface regardless of the type argument.
- List extends Number denotes all list types where the element type is a subtype of Number.
- Comparator super String denotes all instantiations of the Comparator interface for type argument types that are supertypes of String.
- Wildcard вида параметра не является конкретным видом, который может появиться в операторе new. Он только является подсказкой применяющегося правила, с помощью generics java, что какой вид имеет действие в определенном случае, где wildcard был использован.
Collection<?> coll = new ArrayList<String>();
// Набор содержит только вид Number или подвид Number
List<? extends Number> list = new ArrayList<Long>();
// Объект с подстановочным видом параметра.
// (A wildcard parameterized type)
Pair<String,?> pair = new Pair<String,Integer>();
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда- Некоторые недействительные объявления.
// String не является подвидом Number, поэтому ошибка.
List<? extends Number> list = new ArrayList<String>();
// String не является родительским видом Integer, поэтому ошибка.
ArrayList<? super String> cmp = new ArrayList<Integer>();
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда6.1- Examples with wildcard
WildCardExample1.java
package org.wikitechy.tutorial.generics.w;
import java.util.ArrayList;
public class WildCardExample1 {
public static void main(String[] args) {
// Список содержащий элементы вида String.
ArrayList<String> listString = new ArrayList<String>();
listString.add("Tom");
listString.add("Jerry");
// Список содержащий элементы вида Integer
ArrayList<Integer> listInteger = new ArrayList<Integer>();
listInteger.add(100);
// Вы не можете объявить:
ArrayList<Object> list1 = listString; // ==> Error!
// Объект с подстановочным видом параметра.
// (wildcard parameterized object).
ArrayList<? extends Object> list2;
// Вы можете объявить:
//
list2 = listString;
// Или
list2 = listInteger;
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаWildCardExample2.java
package org.wikitechy.tutorial.generics.w;
import java.util.ArrayList;
import java.util.List;
public class WildCardExample2 {
public static void printElement(List<?> list) {
for (Object e : list) {
System.out.println(e);
}
}
public static void main(String[] args) {
List<String> names = new ArrayList<String>();
names.add("Tom");
names.add("Jerry");
names.add("Donald");
List<Integer> values = new ArrayList<Integer>();
values.add(100);
values.add(120);
System.out.println("--- Names --");
printElement(names);
System.out.println("-- Values --");
printElement(values);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда6.2- Тип wildcard parameterized не может использовать методы Generics

java - джава - учиться java - учебник java -
шаблон универсального класса
- примеры java - java-программы
ValidWildcard1.java
package org.wikitechy.tutorial.generics.w;
import java.util.ArrayList;
public class ValidWildcard1 {
public static void main(String[] args) {
// Список содержащий элементы вида String.
ArrayList<String> listString = new ArrayList<String>();
// Использовать метод generic: add(E).
// Добавить элемент не null в список
listString.add("Tom");
listString.add("Jerry");
// Добавить элемент null в список.
listString.add(null);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - командаInvalidWildcard1.java
package org.wikitechy.tutorial.generics.w;
import java.util.ArrayList;
public class InvalidWildcard1 {
public static void main(String[] args) {
// Список с подстановочным видом параметра.
// (wildcard parameterized type).
ArrayList<? extends Object> listWildcard = listString;
// Вы не можете использовать метод add(E)
// с параметром отличающимся от null.
listWildcard.add("Tom"); // ==> Error!
listWildcard.add("Jerry"); // ==> Error!
// Добавить элемент null в список.
listWildcard.add(null);
}
}
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда6.3- Wildcard не может участвовать в new операторе
- Wildcard вида параметра(wildcard parameterized type) не является конкретным видом, и не может появиться в операторе new.
// Параметр Wildcard не может участвовать в операторе new.
List<? extends Object> list= new ArrayList<? extends Object>();
нажмите кнопку ниже, чтобы скопировать код. - от - java tutorials - команда