Java泛型(Generic)是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
官方说明:
When you take an element out of a Collection
, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection’s type, so the cast can fail at run time.
Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.
参照:https://docs.oracle.com/javase/1.5.0/docs/guide/language/generics.html
官网查找路径:
https://www.oracle.com/cn/java/technologies/java-se-api-doc.html
jdk程序员指南-5.0英文版:https://docs.oracle.com/javase/1.5.0/docs/
New Features and Enhancements:https://docs.oracle.com/javase/1.5.0/docs/relnotes/features.html#generics
Generics:https://docs.oracle.com/javase/1.5.0/docs/guide/language/generics.html
泛型程序设计(Generic programming)意味着编写的代码可以被很多不同类型的对象所重用。
存在问题
package com.naixue.vip.p6.before5;
import java.io.File;
/**
* @Description 模拟JDK5以前的没有泛型之前对象重用的问题
* @Author xh
* @Date 2020/7/6 3:04 PM
**/
public class ArrayList {
private int size = 0;
private Object[] elements = {};
public Object get(int i) {
if (size > i) {
return elements[i];
}
throw new IndexOutOfBoundsException();
}
public void add(Object o) {
size++;
Object[] array = new Object[size];
for (int i = 0; i < elements.length; i++) {
array[i]=elements[i];
}
array[size-1]=o;
elements=array;
}
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(1);
arrayList.add("a");
// 这里没有错误检查。可以向数组列表中添加任何类的对象
arrayList.add(new File("/"));
//对于这个调用,编译和运行都不会出错。然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误
String file=(String)arrayList.get(2);
}
}
package com.naixue.vip.p6.evolution;
/**
* @Description 模拟JDK5以前的没有泛型之前对象重用的问题
* @Author xh
* @Date 2020/7/6 3:04 PM
**/
public class ArrayListNew<E> {
private int size = 0;
private Object[] elements = {};
public Object get(int i) {
if (size > i) {
return elements[i];
}
throw new IndexOutOfBoundsException();
}
public void add(E o) {
size++;
Object[] array = new Object[size];
for (int i = 0; i < elements.length; i++) {
array[i]=elements[i];
}
array[size-1]=o;
elements=array;
}
public static void main(String[] args) {
ArrayListNew<String> arrayList = new ArrayListNew<String>();
arrayList.add("a");
String s=(String)arrayList.get(0);
//演示时放开注释
// arrayList.add(1);
// // 编译不通过,不会导致运行后才发生错误
// arrayList.add(new File("/"));
// String file=(String)arrayList.get(2);
}
}
package com.naixue.vip.p6.feature;
import org.junit.Test;
import static junit.framework.TestCase.assertTrue;
/**
* @Description 体现泛型的代码可重用性
* @Author xh
* @Date 2020/7/6 3:04 PM
**/
public class Reuse<T extends Comparable>
{
public Integer compareTo(T t1, T t2) {
return t1.compareTo(t2);
}
@Test
public void testByGenericT()
{
Integer n1=1;
Integer n2=2;
Reuse<Integer> integerReuse =new Reuse<Integer>();
assertTrue(integerReuse.compareTo(n1,n2) == -1);
String s1="100";
String s2="201";
Reuse<String> integerReuse2 =new Reuse<String>();
assertTrue(integerReuse2.compareTo(s1,s2) == -1);
}
}
泛型类(generic class)就是具有一个或多个类型变量的类
public class Pair<T> {
private T first;
private T second;
public Pair() { first = null; second = null; }
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
package com.naixue.vip.p6.funciton;
/**
* @Description 泛型方法的使用
* @Author xh
* @Date 2020/7/6 17:58
**/
public class ArrayAlg {
public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}
public static void main(String[] args) {
String middle =ArrayAlg.<String>getMiddle("a","b","c");
System.out.println(middle);
//因为有两种方式处理。所有的都自动装箱,则得到 两个 Integer 和一个Double
// 之后寻找公共超类 Number 和公共接口 Comparable 于是编译器不知道该如何处理了。
// Integer n =ArrayAlg.getMiddle(1,2,3.2);
// System.out.println(n);
}
}
class
package com.xh.java.wildcard;
import com.xh.java.classes.Pair;
import com.xh.java.vo.Man;
import com.xh.java.vo.Parson;
import com.xh.java.vo.Woman;
/**
* @Description 泛型类型限定只能使用子类
* @Author xh
* @Date 2020/7/6 19:56
**/
public class Programmer<T extends Parson> {
public <T extends Parson> Pair<T> youngAndOld(T[] a) {
if(a == null || a.length == 0) {
return null;
}
T min = a[0];
T max = a[1];
for(int i = 0; i < a.length; i++) {
if(min.getAge().compareTo(a[i].getAge()) > 0) {
min = a[i];
}
if(max.getAge().compareTo(a[i].getAge()) < 0) {
max = a[i];
}
}
return new Pair<>(min, max);
}
public static void main(String[] args) {
Programmer<Parson> programmer = new Programmer<Parson>();
Man man=new Man("陈先生",48,"劳力士","幻影");
Woman woman=new Woman("刘女士",27,"LV","迪奥");
Man man1=new Man("张先生",32,"浪琴","奥迪");
Woman woman1=new Woman("吴女士",18,"LV","圣罗兰");
Parson[] parsons=new Parson[4];
parsons[0]=man;
parsons[1]=woman;
parsons[2]=man1;
parsons[3]=woman1;
Pair<Parson> parsonPair = programmer.youngAndOld(parsons);
//子类型规则,即任何参数化的类型是原生态类型的一个子类型,
//Programmer是Programmer类型的一个子类型,而不是Programmer
// Programmer programmer1 = new Programmer();
// Programmer
}
}