一、为什么需要泛型泛型程序设计(generic programming)意味着编写的代码可以对多种不同类型的对象重用。例如你并不希望为收集String和File对象分别编写不同的类。实际上也不需要这样做因为一个 ArrayList类就可以收集任何类的对象。这就是泛型程序设计的一个例子。实际上在Java有泛型类之前已经有一个ArrayList类。在Java中增加泛型类之前泛型程序设计是用继承实现的。Arraylist类只维护一个Object引用的数组:这种方法存在两个问题当获取一个值时必须进行强制类型转换。此外这里没有错误检查。可以向数组列表中添加任何类的对象。对于这个调用编译和运行都不会出错。不过在其他地方如果将取出的结果强制类型转换为其他子类型可能就会产生一个错误。对于集合来说编译器只知道集合里放的是对象也就是Object类型所以只要是Object类型就可以放在这个集合中ArrayList arrayList new ArrayList(); arrayList.add(new Dog(花花,10)); arrayList.add(new Dog(旺财,6)); arrayList.add(new Dog(奇奇,7)); arrayList.add(new Cat(哈哈,9));在遍历时由于编译器只知道集合中的对象是Object类型所以使用具体类型会报错为了解决以上问题泛型这个概念就出现了泛型类和泛型方法有类型参数这使得它们可以准确地描述用特定类型实例化时会发生什么。在有泛型类之前程序员必须使用Object编写适用于多种类型的代码。这很烦琐也很不安全。随着泛型的引人Java有了一个表述能力很强的类型系统允许设计者详细地描述变量和方法的类型要如何变化。对于简单的情况你会发现实现泛型代码很容易。不过在更高级的情况下对于实现者来说这会相当复杂。其目标是提供让其他程序员可以轻松使用的类和方法而不会出现意外。Java 5中泛型的引入成为Java程序设计语言自最初发行以来最显著的变化。Java的一个主要设计目标是支持与之前版本的兼容性。因此Java的泛型有一些让人不快的局限性。二、泛型介绍三、泛型的语法public class Main { public static void main(String[] args) { person person new personString,Integer(); System.out.println(person.getClass()); } } class personE,N{ E name; N age; public person() { } public person(E name, N age) { this.name name; this.age age; } }E和N的具体数据类型在创建这个类的对象时指定即在编译时期就确定E和N什么类型只能是引用数据类型不能是基本数据类型实际开发中我们一般不全写我们往往会采用简写方式编译器会根据前面的String帮我们推断出后面中也是String;格式public class 类名 泛型类型1,... { }例如public class GenericClassab,a,c {}理论上参数类型可以是任意字母当然它也是有规范的通常类型参数我们都使用大写的单个字母表示E - Element (在集合中使用因为集合中存放的是元素)T - TypeJava 类K - Key键V - Value值N - Number数值类型 - 表示不确定的 java 类型四、自定义泛型①自定义泛型类②自定义泛型接口对于这样的一个泛型接口public interface IUsbU, R { public abstract R get(U u); public abstract void hi(R r); public abstract void run(R r1, R r2, R r3, R r4); public default R method(U u) { return null; } }需要在继承接口或者实现接口时指定其具体类型编译器就会知道子接口用什么类型Ⅰ.继承接口interface IA extends IUsbString,Integer{ Override Integer get(String s); Override void hi(Integer integer); Override void run(Integer r1, Integer r2, Integer r3, Integer r4); Override default Integer method(String s) { return IUsb.super.method(s); } }Ⅱ.实现接口class AA implements IUsbString,Double{ Override public Double get(String s) { return null; } Override public void hi(Double aDouble) { } Override public void run(Double r1, Double r2, Double r3, Double r4) { } Override public Double method(String s) { return IUsb.super.method(s); } }Ⅲ.注意事项因为具体类型在编译时就要确定如果不指定具体类型默认为Objectinterface IA extends IUsb{ Override Object get(Object o); Override void hi(Object o); Override void run(Object r1, Object r2, Object r3, Object r4); Override default Object method(Object o) { return IUsb.super.method(o); } }class AA implements IUsb{ Override public Object get(Object o) { return null; } Override public void hi(Object o) { } Override public void run(Object r1, Object r2, Object r3, Object r4) { } Override public Object method(Object o) { return IUsb.super.method(o); } }③自定义泛型方法非静态方法静态方法泛型方法与可变参数Ⅰ.泛型方法可定义在普通类中public class Main { public static void main(String[] args) { Car car new Car(); // 使用泛型方法直接在参数列表中传入参数编译器会确定类型 car.fly(hjhdjs,100); } } class Car{ public void run(){ } // 1.T,R为泛型标识符代表这是个泛型方法 public T,R void fly(T t,R r){ } }Ⅱ.泛型方法可定义在泛型类中class FishT, R { public void run() { } public U, M void eat(U u, M m) { // 泛型方法 } }Ⅲ.注意事项泛型方法既可以使用类声明的泛型也可以使用自己声明的泛型对于以下方法public void run(T t) { }只能说它使用了类声明的泛型它不是一个泛型方法五、泛型的继承和通配符5.1无界通配符语法结构示例5.2通配符的上限限定语法结构示例5.3通配符的下限限定语法结构示例六、泛型总结