JavaSE学习笔记(十七)—— JDK5新特性之泛型
一、泛型概述
1.1 泛型引入
先看下面代码:
public class GenericDemo { public static void main(String[] args) { ArrayList list = new ArrayList(); // 添加元素 list.add("hello"); list.add("world"); list.add("java"); // array.add(new Integer(100)); list.add(10);// JDK5以后的自动装箱,list.add(Integer.valueOf(10)); // 遍历 Iterator it = list.iterator(); while (it.hasNext()) { String s = (String) it.next(); System.out.println(s); } } }
我们按照正常的写法来写这个程序,结果却出错了。
为什么呢?
因为我们开始存储的时候,存储了String和Integer两种类型的数据。而在遍历的时候,我们把它们都当作String类型处理的,做了转换,所以就报错了。
但是呢,它在编译期间却没有告诉我们。所以,我就觉得这个设计的不好。
回想一下,我们的数组:
String[] strArray = new String[3]; strArray[0] = "hello"; strArray[1] = "world"; //strArray[2] = 10;编译期间就报错,因为已经指定数组要存储的类型是String,而你却往里面装Integer类型,所以编译失败
集合也模仿着数组的这种做法,在创建对象的时候明确元素的数据类型。这样就不会在有问题了。而这种技术被称为:泛型。
1.2 为什么会有泛型
定义ObjectTool.java
public class ObjectTool { private Object obj; public Object getObj() { return obj; } public void setObj(Object obj) { // Object obj = new Integer(30); this.obj = obj; } }
测试:
public class ObjectToolDemo { public static void main(String[] args) { ObjectTool ot = new ObjectTool(); // 正常使用 ot.setObj(new Integer(27)); 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(30)); // ClassCastException String ss = (String) ot.getObj(); System.out.println("姓名是:" + ss); } }
早期的时候,我们使用Object来代表任意的类型。向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。也就是说这样的程序其实并不是安全的。所以Java在JDK5后引入了泛型,提高程序的安全性。
1.3 泛型介绍
泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。也被称为参数化类型,可以把类型当作参数一样传递过来,在传递过来之前我不明确,但是在使用的时候我就用明确了。
泛型是JDK1.5版本以后出现的新特性,它用于解决安全问题,是一个类型安全机制。
泛型一般在集合中使用。
【格式】
<数据类型>
此处的数据类型只能是引用类型。
【好处】
A:将运行时期出现问题ClassCastException,提前到了编译时期。方便于程序员解决问题。让运行时问题减少,安全。
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线
【案例】
存储字符串并遍历
public class ArrayListDemo { 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); } } }
存储自定义对象并遍历。
public class ArrayListDemo2 { public static void main(String[] args) { // 创建集合对象 // JDK7的新特性:泛型推断。 ArrayList<Student> array = new ArrayList<>(); // 创建元素对象 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()); } } }
二、泛型的应用
2.1 泛型类
把泛型定义在类上,被称为泛型类。
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
【案例】
定义一个泛型类
/* * 泛型类:把泛型定义在类上 */ public class ObjectTool<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } }
泛型类测试
public class ObjectToolDemo { public static void main(String[] args) { ObjectTool<String> ot = new ObjectTool<>(); ot.setObj("林青霞"); String s = ot.getObj(); System.out.println("姓名是:" + s); ObjectTool<Integer> ot2 = new ObjectTool<Integer>(); // ot2.setObj(new String("风清扬"));//这个时候编译期间就过不去 ot2.setObj(new Integer(27)); Integer i = ot2.getObj(); System.out.println("年龄是:" + i); } }
2.2 泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
【示例】
/* * 泛型方法:把泛型定义在方法上 */ public class ObjectTool { public <T> void show(T t) { System.out.println(t); } }
public class ObjectToolDemo { public static void main(String[] args) { ObjectTool ot = new ObjectTool(); ot.show("hello"); ot.show(100); ot.show(true); } }
2.3 泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
【示例】
定义泛型接口
/* * 泛型接口:把泛型定义在接口上 */ public interface Inter<T> { public abstract void show(T t); }
接口实现类:
public class InterImpl<T> implements Inter<T> { @Override public void show(T t) { System.out.println(t); } }
测试:
public class InterDemo { public static void main(String[] args) { InterImpl<String> i = new InterImpl<>(); i.show("hello"); InterImpl<Integer> ii = new InterImpl<>(); ii.show(100); } }
三、泛型高级(通配符)
?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E:向下限定,E及其子类
? super E:向上限定,E及其父类
public class GenericDemo { 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 { }