1.体验泛型

  泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时去除掉“类型”信息,使程序运行小效率不受影响,对于参数化的泛型类型,getClass()方法返回值和原始类型完全一样.由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,在调用其add方法即可.

  ArrayList<String> collection1 = new ArrayList<String>();

  ArrayList<Integer> collection2 = new ArrayList<Integer>();

  System.out.println(collection1.getClass() == collection2.getClass()); //true

  

  1. public static void main(String[] args) throws Exception {
  2. ArrayList<String> collection1 = new ArrayList<>();
  3. collection1.add("abc");
  4. ArrayList<Integer> collection2 = new ArrayList<>();
  5. System.out.println(collection1.getClass() == collection2.getClass()); //true
  6. collection2.getClass().getMethod("add", Object.class).invoke(collection2, "abc");
  7. System.out.println(collection2.get(0)); //abc
  8. }

  参数化类型不考虑类型参数的继承关系:

  Vector<String> v1 = new Vector<Object>();//错误!不写<Object>没错

  Vector<Object> v2 = new Vetcor<String>(); //错误

  在创建数组时,数组的元素不能使用参数化的类型,例如,下面语句有误

    Vector<Integer> vectorList[] = new Vector<Integer>[10];

  思考题:下面代码会报错么?

  Vector v1 = new Vector<String>();  //参数化类型给原始类,不报错

  Vector<Object> v2 = v1 ;           //原始类型给参数化类型,可以

2.泛型的通配符扩展应用

  泛型中的 ? 通配符

    ?表示任意类型

    定义一个方法,该方法用于打印出任意参数化类型集合中的所有数据,该方法如何定义?

    

  1. public void printCollection(Collection<?> cols){
  2. for(Object obj: cols){
  3. System.out.println(obj);
  4. }
  5. //cols.add("string") //错误,因为它不知道自己未来匹配就一定是String add()方法跟类型参数有关系
  6. cols.size(); //没错,此方法与类型参数没有关系
  7. cols=new HashSet<Date>(); //? 可以引用其他类型
  8. }

  总结:

  使用 ?  通配符可以引用其他各种参数的类型, ? 通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

  限定通配符的上边界:

    正确: Vector<? extends Number> x = new Vector<Integer>();

    错误:Vector<? extends Number> x = new Vector<String>();

  限定通配符的下边界:

    正确:Vector<? super Integer> x = new Vector<Number>();

    错误:Vector<? super Integer> x = new Vector<Byte>();  //要求参数类型需是Integer的父类就为Number或者Number的父类。

  限定通配符总是包括自己。

  泛型集合的综合应用案例

  对在jsp页面中也经常要对Set或Map集合进行迭代:

  <c:forEach items="${map}" var="entry">

    ${entry.key}:${entry.value}

  </c:forEach>

3.定义泛型方法

  交换数组中的两个元素的位置的泛型方法语法定义如下:

  static <E> void swap(E[] int i,int j){

    E t = E[i];

    E[i] = E[j];

    E[j] = t;

  }

  >用于防止泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回值类型之前,

  也就是紧邻返回值之前。按照惯例,类型参数通常用打那个大写字母表示。

  >只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5);语句会报告编译错误。

  > 然而对于add方法,使用基本类型的数据进行测试没有问题,这是因为自动装箱和自动拆箱了。

4.泛型方法的练习

  >编写一个方法,自动将Object 类型的对象转换成其他类型

  1. public static void main(String[] args) throws Exception {
  2. Object obj = "abc";
  3. String x3 = autoConvert(obj);
  4. }
  5. private static <T> T autoConvert(Object obj){//在返回值的前边,用一个<>来说明类型,或者传递一个新的类型
  6. return (T)obj;
  7. }

5.自定义泛型类

  1. package com.java.day2;
  2.  
  3. import java.util.Set;
  4.  
  5. /**
  6. * 自定义泛型类
  7. * @author Administrator
  8. *
  9. * @param <E>
  10. */
  11. public class GenericDao<E> { //类中说明类对象中使用的是同一中参数
  12.  
  13. public void add(E x){
  14.  
  15. }
  16.  
  17. public E findById(int id){
  18. return null;
  19. }
  20.  
  21. public void delete(E obj){
  22.  
  23. }
  24.  
  25. public void delete(int id){
  26.  
  27. }
  28.  
  29. public void update(E obj){
  30.  
  31. }

    public static <E> void update2(E obj){

    }

  1. public Set<E> findByConditions(String where){
  2. return null;
  3. }
  4. }

GenericDao<ReflectPoint> dao = new GenericDao<>();

注意:静态方法中不能使用与类相同的范型类型(静态方法执行时,类还没有实例化)

public static <E> void update2(E obj){

}

这样写就认为是独立的,跟类没有关系了。

编译器的去泛型类型化

  编译器编译后认为两个是相同的(这不是重载)

  

 6. 通过反射获得泛型的实际类型参数

  1. public static void main(String[] args) throws NoSuchMethodException, SecurityException {
  2. Object obj = "abc";
  3. String x3 = autoConvert(obj);
  4. System.out.println(x3);
  5.  
  6. Vector<Date> v1 = new Vector<Date>();
  7. //通过变量名成 v1是无法得到 实际的泛型参数类型,但是把这个变量传给一个方法使用时
  8. //可以通过反射,得到方法的实际参数类型的
  9.  
  10. //通过反射的方式,得到泛型里的实际类型
  11. Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
  12. Type[] types = applyMethod.getGenericParameterTypes(); //获取参数的泛型类型,返回数组
  13. ParameterizedType pType = (ParameterizedType) types[0]; //方法中的第一个参数
  14. System.out.println(pType.getRawType()); //获取原始的类型 class java.util.Vector
  15. //很多数据库框架用了此方法,把数据库查询出的记录,转为实际的参数类型,必须先得到实际的参数化类型
  16. //
  17. System.out.println(pType.getActualTypeArguments()[0]); //得到实际参数化类型,可能有多个Map<K,V> class java.util.Date
  18. }
  19.  
  20. public static void applyVector(Vector<Date> v1){
  21.  
  22. }

 很多框架就是根据这个方法,把数据库查出的对象转换成泛型的实际化参数(前提需要获取得知泛型的实际化参数是什么类型的)

 Hibernate 就是利用此方法,获取泛型的实际化参数类型

java高新技术-泛型的更多相关文章

  1. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  2. Java 中泛型的全面解析(转)

    Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ...

  3. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  4. Java 泛型 Java使用泛型的意义

    Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...

  5. 跟着刚哥梳理java知识点——泛型(十三)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...

  6. Java高新技术 注解

      Java高新技术 注解 知识概要:                  (1)了解注解 (2)注解的应用结构图 (3)@Retention(RetentionPolicy.RUNTIME)    ...

  7. Java高新技术 JavaBean内省

     Java高新技术  JavaBean内省 知识概要:                 (1)了解JavaBean内省                 (2)JavaBean的简单内省操作     ...

  8. Java高新技术 反射机制

     Java高新技术 反射机制 知识概要:                   (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...

  9. Java高新技术 JDK1.5之新特性

      Java高新技术  JDK1.5的新特性 知识概要:                 (1)静态导入 (2)可变参数 (3)增强for循环 (4)基本数据类型的自动拆箱和装箱 静态导入     ...

随机推荐

  1. ie6-ie8中不支持opacity透明度的解决方法

    ie6-ie8中是不支持的,需要加上下面这句话:filter: alpha(opacity=70);此外这种效果不能用ietester中的ie6测试,因为ietester的ie6这样写也是不透明的,但 ...

  2. 返回标量CLR自定义函数

    昨天有学习了返回表自定义函数<CLR Table-Valued函数>http://www.cnblogs.com/insus/p/4378354.html.今天学习另一个,实现返回标量(S ...

  3. 清北学堂2017NOIP冬令营入学测试P4749 C’s problem(c)

    P4746 C's problem(c) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 题目描述 小C是一名数学家,由于它自制力比较差 ...

  4. ASP.NET MVC 教程-MVC简介

    ASP.NET 是一个使用 HTML.CSS.JavaScript 和服务器脚本创建网页和网站的开发框架. ASP.NET 支持三种不同的开发模式:Web Pages(Web 页面).MVC(Mode ...

  5. matlab jet color mapping C / C++ / VC 实现

    在matlab中调用imagesc()将一幅灰阶图像以彩色显示时,默认使用的color mapping是Jet,其color bar 为: Jet的color mapping图为: Color map ...

  6. TM4C123G红外触摸屏:开发板好不容易实现了原理,放到专家设计的板子上无法运行,于是专家跑路项目黄了

    使用TI的TM4C123G LaunchPad开发板,USB接口,来对同样的芯片进行烧写. 我们只用烧写那一块功能,不用另外一个芯片的开发功能,需要跳线   源码项目:   从官方网站TM4C123G ...

  7. C#访问Azure的资源

    官方参考资料在这里:https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx,本文放一些重点及遇到的坑的解决办法. 身份验证 不是说,我 ...

  8. nios II--实验1——hello_world软件部分

    hello_world 软件开发 首先,在硬件工程文件夹里面新建一个software的文件夹用于放置软件部分:打开toolsàNios II 11.0 Software Build Tools for ...

  9. SD卡状态广播

    SD状态发生改变的时候会对外发送广播.SD卡的状态一般有挂载.未挂载和无SD卡. 清单文件 一个广播接受者可以接受多条广播.这里在意图过滤器中添加是data属性是因为广播也需要进行匹配的.对方发送的广 ...

  10. 自然数从1到n之间,有多少个数字含有1

        问题明确而简单.for循环肯定是不好的.       用递推方法:       定义h(n)=从1到9999.....9999  ( n 个 9)之间含有1的数字的个数.定义f(n)为n位数中 ...