1、泛型概述及使用
JDK1.5以后出现的机制
泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。也被称为参数化类型,可以把类型当作参数一样传递过来,在传递过来之前我不明确,但是在使用的时候我就要明确了。
2、泛型的好处
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线
3、格式
<数据类型>
此处的数据类型只能是引用类型。
例子1:
package genericdemos; import java.util.ArrayList; import java.util.Iterator; /** * Created by gao on 15-12-15. */ public class GenericDemo01 { public static void main(String[] args) { //创建 ArrayList<String> arrayList = new ArrayList<String>(); // 添加元素 arrayList.add("hello"); arrayList.add("world"); arrayList.add("java"); //遍历 Iterator<String> it = arrayList.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } } }
例子2:泛型为字符串
package genericdemos; import java.util.ArrayList; import java.util.Iterator; /** * Created by gao on 15-12-15. */ /* * 泛型在哪些地方使用呢? * 看API,如果类,接口,抽象类后面跟的有<E>就说要使用泛型。一般来说就是在集合中使用。 */ public class GenericDemo02 { public static void main(String[] args) { // 用ArrayList存储字符串元素,并遍历。用泛型改进代码 ArrayList<String> array = new ArrayList<String>(); array.add("hello"); array.add("world"); array.add("java"); Iterator<String> it = array.iterator(); while (it.hasNext()) { String s = it.next(); System.out.println(s); } System.out.println("-----------------"); for (int x = 0; x < array.size(); x++) { String s = array.get(x); System.out.println(s); } } }
例子3:泛型是自定义对象
Student类:
package genericdemos; /** * Created by gao on 15-12-9. */ public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
测试类:
package genericdemos; import java.util.ArrayList; import java.util.Iterator; /** * Created by gao on 15-12-15. */ /* * 需求:存储自定义对象并遍历。 * * A:创建学生类 * B:创建集合对象 * C:创建元素对象 * D:把元素添加到集合 * E:遍历集合 */ public class GenericDemo03 { public static void main(String[] args) { // 创建集合对象 ArrayList<Student> array = new ArrayList<Student>(); // 创建元素对象 Student s1 = new Student("曹操", 40); // 后知后觉 Student s2 = new Student("蒋干", 30); // 不知不觉 Student s3 = new Student("诸葛亮", 26);// 先知先觉 // 添加元素 array.add(s1); array.add(s2); array.add(s3); Iterator<Student> it = array.iterator(); while (it.hasNext()) { Student s = it.next(); System.out.println(s.getName() + "---" + s.getAge()); } System.out.println("------------------"); for (int x = 0; x < array.size(); x++) { Student s = array.get(x); System.out.println(s.getName() + "----" + s.getAge()); } } }
4、泛型由来
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
5、泛型的应用
例子4:自定义Object工具类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class ObjectTool { private Object obj; public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } }
测试类:
package genericdemos; /** * Created by gao on 15-12-15. */ /* * 早期的时候,我们使用Object来代表任意的类型。 * 向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。 * 也就是说这样的程序其实并不是安全的。所以Java在JDK5后引入了泛型,提高程序的安全性。 */ public class GenericDemo04 { public static void main(String[] args) { ObjectTool ot = new ObjectTool(); // 正常使用 ot.setObj(new Integer(24)); Integer i = (Integer) ot.getObj(); System.out.println("年龄是:" + i); ot.setObj(new String("林青霞")); String s = (String) ot.getObj(); System.out.println("姓名是:" + s); System.out.println("------------"); // ot.setObj(new Integer(123)); // //Integer cannot be cast to java.lang.String // String s1 = (String) ot.getObj(); // System.out.println(s1); } }
泛型类:把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
例子5:
package genericdemos; /* * 泛型类:把泛型定义在类上 */ public class ObjectTool<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } }
测试类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class ObjectToolTest { public static void main(String[] args) { ObjectTool<String> ot = new ObjectTool<String>(); //ot.setObj(new Integer(27)); //这个时候编译期间就过不去 ot.setObj(new String("林青霞")); String s = ot.getObj(); System.out.println("姓名是:" + s); ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); //ot2.setObj(new String("风清扬")); //这个时候编译期间就过不去 ot2.setObj(new Integer(25)); Integer i = ot2.getObj(); System.out.println("年龄是:" + i); } }
例子6:方法的重载用泛型改进
泛型类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class ObjectTool2<T> { // // public void show(String s) { // // System.out.println(s); // // } // // // // public void show(Integer i) { // // System.out.println(i); // // } // // // // public void show(Boolean b) { // // System.out.println(b); // // } // // public void show(T t) { // System.out.println(t); // } // } public void show(T t) { System.out.println(t); } }
测试类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class ObjectToolTest2 { public static void main(String[] args) { // ObjectTool ot = new ObjectTool(); // ot.show("hello"); // ot.show(100); // ot.show(true); ObjectTool2<String> ot = new ObjectTool2<String>(); ot.show("hello"); ObjectTool2<Integer> ot2 = new ObjectTool2<Integer>(); ot2.show(100); ObjectTool2<Boolean> ot3 = new ObjectTool2<Boolean>(); ot3.show(true); } }
输出结果:
hello
100
true
泛型方法:把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
例子7:直接使用泛型方法
泛型方法所在的类:
package genericdemos; /** * 泛型方法:把泛型定义在方法上 */ public class ObjectTool3 { public <T> void show(T t) { System.out.println(t); } }
测试类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class ObjectToolTest3 { public static void main(String[] args) { // 定义泛型方法后 ObjectTool3 ot = new ObjectTool3(); ot.show("hello"); ot.show(100); ot.show(true); } }
输出结果:
hello
100
true
泛型接口:把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
例子8:
泛型接口:
package genericdemos; /** * Created by gao on 15-12-15. */ /* * 泛型接口:把泛型定义在接口上 */ public interface Inter<T> { public abstract void show(T t); }
接口实现类:
package genericdemos; /** * Created by gao on 15-12-15. */ //实现类在实现接口的时候 //第一种情况:已经知道该是什么类型的了 //public class InterImpl implements Inter<String> { // @Override // public void show(String t) { // System.out.println(t); // } //} //第二种情况:还不知道是什么类型的 public class InterImpl<T> implements Inter<T> { @Override public void show(T t) { System.out.println(t); } }
测试类:
package genericdemos; /** * Created by gao on 15-12-15. */ public class InterDemo { public static void main(String[] args) { // 第一种情况的测试 // Inter<String> i = new InterImpl(); // i.show("hello world"); //hello world // 第二种情况的测试 Inter<String> i = new InterImpl<String>(); i.show("hello world"); //hello world Inter<Integer> ii = new InterImpl<Integer>(); ii.show(1234); //1234 } }
6、泛型高级(通配符)
1)泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
2)? extends E
向下限定,E及其子类
3)? super E
向上限定,E及其父类
package genericdemos; import java.util.ArrayList; import java.util.Collection; /** * Created by gao on 15-12-15. */ public class GenericDemo05 { public static void main(String[] args) { // 泛型如果明确的写的时候,前后必须一致 Collection<Object> c1 = new ArrayList<Object>(); // Collection<Object> c2 = new ArrayList<Animal>(); // Collection<Object> c3 = new ArrayList<Dog>(); // Collection<Object> c4 = new ArrayList<Cat>(); // ?表示任意的类型都是可以的 Collection<?> c5 = new ArrayList<Object>(); Collection<?> c6 = new ArrayList<Animal>(); Collection<?> c7 = new ArrayList<Dog>(); Collection<?> c8 = new ArrayList<Cat>(); // ? extends E:向下限定,E及其子类 // Collection<? extends Animal> c9 = new ArrayList<Object>(); Collection<? extends Animal> c10 = new ArrayList<Animal>(); Collection<? extends Animal> c11 = new ArrayList<Dog>(); Collection<? extends Animal> c12 = new ArrayList<Cat>(); // ? super E:向上限定,E极其父类 Collection<? super Animal> c13 = new ArrayList<Object>(); Collection<? super Animal> c14 = new ArrayList<Animal>(); // Collection<? super Animal> c15 = new ArrayList<Dog>(); // Collection<? super Animal> c16 = new ArrayList<Cat>(); } } class Animal{ } class Dog extends Animal{ } class Cat extends Animal{ }