java泛型总结学习
来源:互联网 发布:淘粉吧登陆淘宝安全 编辑:程序博客网 时间:2024/06/13 06:40
什么是泛型?
- 泛型 , 即 “参数化类型” . 提到参数 , 最熟悉的就是定义方法时有形参 , 然后调用方法传递实参 . 那么参数化类型如何理解? 就是将类型由原来具体的类型参数化 , 类似于方法中的变量参数 , 此时类型也定义成参数形式 , 然后在调用的时候传入具体的类型 .
下面采用泛型后, 当通过List<’String> , 就相当于给List传递了参数类型是String, 限定了集合中只能含有String类型元素 , 集合保存了这个类型, 当add(“123”) , 无需进行类型转换 , 因为编译器明确可以传递String类型 . 当然如果传入Integer类型是不会通过编译的 . - java中一种类型 , 被参数化的类型 , 也就是可以通过参数传递类型 . 带参数的类型就是泛型 , 被参数化的类型 .
泛型擦除:
java泛型概念的提出 , 导致泛型只是作用于代码的编译阶段 , 在编译过程中 , 对于正确的检验泛型结果后 , 会将泛型的相关信息擦除 , 也就是说 , 成功编译过后的class文件是不包含任何的泛型信息的 . 泛型信息不会进入运行时阶段 .
泛型其实只是在编译器实现的,而虚拟机并不认识泛型类型,所以要在虚拟机中将泛型类型进行擦除 , 也就是说编译阶段使用泛型 , 运行阶段取消泛型 ,
擦除是将泛型类型由父类代替的 , 如String变成Object , 其实使用的时候还是带着强制的类型转换 , 只不过这是比较安全的转换 , 因为在编译阶段已经确保数据的一致性 .
验证泛型只在编译器有效:
所有反射操作是在运行期, 既然是true, 说明编译之后, 程序会采用去泛型化措施 ,
编译过程中, 正确检验泛型结果后, 会将泛型的相关信息擦除, 并且在对象进入和离开方法的边界处添加类型检查和类型转换方法, 也就是说成功编译后的class方法是不包含任何泛型信息的
public static void main(String[] args) { List<String> stringList = new ArrayList<>(); List commonList = new ArrayList(); // 说明运行期字节码文件是相同的 System.out.println(stringList.getClass() == commonList.getClass()); // true }
利用反射跳过泛型检查:
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("zhangsan"); // 利用泛型进行添加 try{ Class clazz = list.getClass(); Method method = clazz.getMethod("add", Object.class); // 添加Integer类型数据, 因为反射是在运行期, 说明泛型的检验是在编译期 method.invoke(list, 100); } catch (Exception e) { e.printStackTrace(); } System.out.println(list); }
泛型通配符:
对于任意(引用)类型 T,ArrayList<’?> 类型是ArrayList<’T> 的超类型(类似原始类型 ArrayList 和根类型 Object)。
但是ArrayList<’Object>并不是ArrayList<’String>的超类型.
泛型上下限:
T super Number,那么T就是Number父类级别的类型,
T extends Number 的话,Number是T的父级别类型.
应用:
- 获取下面test方法的形参中泛型的参数类型.
public class Test { /** * 三个参数, 只有两个是泛型类型参数 * @param map * @param list * @param str */ public void test(Map<String,Integer> map, List<String> list, String str) { System.out.println("hello world"); } public static void main(String[] args) { try { Method method = Test.class.getMethod ("test", Map.class, List.class, String.class); // 获取方法的形参 Type[] paramterTypes = method.getGenericParameterTypes(); // 遍历所有类型, 判断是否是泛型的类型 for(Type type : paramterTypes) { if(type instanceof ParameterizedType) { Type[] ts = ((ParameterizedType)type).getActualTypeArguments(); for(Type t : ts) { // 打印结果:String Integer String System.out.println(((Class)t).getSimpleName()); } } } }catch(Exception e) { e.printStackTrace(); } }}
- 比如在三大框架整合中, 我们需要将所有增删改查操作方法放在父类中, UserService操作的实体类型是User, DepartService操作类型是Depart . 那么如何让父类BaseService获得到子类操作的实体类型(Hibernate中增删改查需要获取实体类型名称) ?
父类:
public class BaseService<T> { private Class<T> clazz; @SuppressWarnings("unchecked") public BaseService() { // 获取子类的class对象 Class c = (Class<T>) this.getClass(); // 获取子类的extend类型 Type type = c.getGenericSuperclass(); // 判断是否是泛型 if(type instanceof ParameterizedType) { // 获取泛型的参数类型(默认获取第一个) Type t = ((ParameterizedType)type).getActualTypeArguments()[0]; clazz = (Class<T>) t; System.out.println(clazz.getSimpleName()); } }}
UserService:
public class UserService extends BaseService<User> { public static void main(String[] args) { new UserService(); // User }}
DepartService:
public class DepartService extends BaseService<Depart> { public static void main(String[] args) { new DepartService(); // Depart }}
泛型好处 :
(1) 类型安全
通过泛型定义的变量类型限制, 编译器可以很有效的提高java程序的类型安全 .
(2) 消除强制类型转换
消除强制类型转换, 使得代码更加可读, 并减少出错的机会, 所有的强制转换都是自动
- java泛型总结学习
- java泛型总结学习
- 【Java学习】Java泛型知识点总结
- 泛型之Java学习总结
- java泛型的学习总结
- 黑马程序员---java泛型学习总结
- JAVA学习总结之泛型
- Java学习总结第二十九天Java泛型应用
- 黑马程序员 java泛型学习总结(一)
- 黑马程序员 java泛型学习总结(二)
- 黑马程序员---关于学习Java泛型的一些总结
- Java高级特性之泛型学习总结
- 泛型学习总结
- 泛型学习总结
- java框架学习总结
- java学习一路总结
- java线程学习总结
- JAVA SWING学习总结
- 从一个小例子来看setInterval的使用
- HttpUtility.UrlDecode(),HttpUtility()escape()、encodeURI()、encodeURIComponent()区别详解以及相应的前台解码和.net后台解码
- Mongodb缓存的使用
- 总结学习 —— 前置定义
- ThreadLocal源码分析
- java泛型总结学习
- python csv文件读取reader
- Mysql常用sql(函数)
- CSS清除浮动大全共8种方法
- 系统相簿界面,通讯录界面等后标题显示的英文
- redis3.0配置文件redis.conf详解
- POJ 3280 Cheapest Palindrome (区间DP)
- IOS 自定义UITabBarController的高度处理
- 空间长图