Java1.5新特性之泛型

来源:互联网 发布:网络公开课 麻省 网 编辑:程序博客网 时间:2024/06/05 08:28

在JDK1.5之前我们使用集合都是没有类型限制的,如下:

public class FanXingTest {public static void main(String[] args) {/*创建一个集合*/Collection collection = new ArrayList();/*往集合中添加数据*/collection.add(1);collection.add("hello");/*输出集合中的数据*/System.out.println(collection);}}

JDK1.5的集合类型希望你在定义集合时,明确表示你要向集合中添加的数据的类型,如下程序表示只能添加Integer类型的数据:

public class FanXingTest {public static void main(String[] args) {/*创建一个集合*/Collection<Integer> collection = new ArrayList<Integer>();/*往集合中添加数据*/collection.add(1);/*强行往只能存储Integer类型的集合中添加String类型数据,就会报错*///collection.add("hello");/*输出集合中的数据*/System.out.println(collection);}}

泛型是提供给java编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型的集合时会去掉“类型信息”,使程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能够跳过编译器【使用反射机制可以跳过编译器】,就可以往某个泛型集合中加入其他类型的数据。


下面这个程序充分说明了泛型的去类型化:

public class AddOtherType {public static void main(String[] args) throws Exception {/*创建一个List集合*/List<Integer> list = new ArrayList<Integer>();/*因为泛型类型是Integer类型,所以现在只能往集合中添加Integer类型数据*/list.add(168);/*我们通过反射机制直接获取集合的字节码【此时泛型的类型已经被去掉了】,然后往集合中添加String类型的字符串*/list.getClass().getMethod("add", Object.class).invoke(list, "廖泽民");/*不信的话,我们可以从中把字符串打印出来*/System.out.println(list.get(1));}}

不同类型的集合,其实他们的字节码是一样的:

public class AddOtherType {public static void main(String[] args) throws Exception {/*创建一个Integer类型的List集合*/List<Integer> list = new ArrayList<Integer>();/*因为泛型类型是Integer类型,所以现在只能往集合中添加Integer类型数据*/list.add(168);/*创建String类型的集合*/List<String> list1 = new ArrayList<String>();/*程序输出true,这也说明了,程序在编译时已经忽略了类型*/System.out.println(list.getClass() == list1.getClass());}}


使用entrySet遍历带泛型的Map集合:

public class AddOtherType {public static void main(String[] args) throws Exception {/*创建一个带泛型的map集合*/Map<String, Integer> maps = new HashMap<String, Integer>();/*往集合中添加数据*/maps.put("id", 168);maps.put("age", 22);/*调用entrySet()方法将map中的元素封装为一个Set集合*/Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();for (Map.Entry<String, Integer> entry : entrySet){System.out.println(entry.getKey() + "||"+ entry.getValue());}}}


概念介绍:

ArrayList<T>:称为ArrayList<T>泛型类型。

ArrayList<T>:T称为类型变量和类型参数。

ArrayList<Integer>:Integer称为参数的实例或实际类型参数。

ArrayList<Integer>:<>为typeOf。

ArrayList称为原始类型。

参数化类型和原始类型可以兼容:

Collection<Integer> c = new ArrayList();这是正确的写法。

Collection c = new ArrayList<Integer>();这也是正确的写法。

千万要记住:泛型中的类型不存在继承关系!

ArrayList<String> list = new ArrayList<Object>():这是错误的!!!

ArrayList<Object> list = new ArrayList<String>():这也是错误的!!!


泛型中的通配符:?

使用?通配符可以引用其他各种参数化的类型。

限定通配符的上边界:

List<? extends Number> list = new ArrayList<Integer>():?extends Number表示new 集合的泛型类型必须是Number的子类或本身。

限定通配符的下边界:

List<? super Integer> list = new ArrayList<Number>():  ?super Integer表示new集合的泛型类型必须是Integer的父类或本身。

public class AddOtherType {public static void main(String[] args) throws Exception {/* 创建一个Integer类型的List集合 */List<Integer> list = new ArrayList<Integer>();/* 因为泛型类型是Integer类型,所以现在只能往集合中添加Integer类型数据 */list.add(168);list.add(520);/*调用通配符方法进行打印*/displayCollection(list);}/** * 使用?通配符打印集合 * @param collection  *  * ? extends Object表示传过来的泛型类型必须是Object的子类 *             */public static void displayCollection(Collection<? extends Object> collection) {for (Object obj : collection) {System.out.println(obj);}}}

自定义泛型方法:

在返回值类型前面加上<T>,如:public static <T> T add(T x, T y)。

如下程序展示了自定义泛型方法:

public class AddOtherType {public static void main(String[] args) throws Exception {/* 创建一个Integer类型的List集合 */List<Integer> list = new ArrayList<Integer>();/* 因为泛型类型是Integer类型,所以现在只能往集合中添加Integer类型数据 */list.add(168);list.add(520);/*调用通配符方法进行打印*/showCollection(list);}/** * 自定泛型方法打印集合 * 一般步骤是在返回类型前面加<T> * 比如这个方法返回类型是void,所以:<T> void * @param collection */public static <T> void showCollection(Collection<T> collection){for (Object obj : collection){System.out.println(obj);}}}

自定义泛型类:有时候我们在定义类的时候就想要使这个类今后可以操作指定的实体,此时我们可以使用泛型【泛型类的创建是在类名后面加<T>】!

public interface IBaseDAO<T> {/** * 获取记录总数 * @param entityClass 实体类 * @return */public long getCount();/** * 清除一级缓存的数据 */public void clear();/** * 保存实体 * @param entity 实体id */public void save(T entity);/** * 更新实体 * @param entity 实体id */public void update(T entity);/** * 删除实体 * @param entityClass 实体类 * @param entityids 实体id数组 */public void delete(Serializable ... entityids);}


0 0