java泛型总结学习
2017-03-17 17:50
344 查看
什么是泛型?
泛型 , 即 “参数化类型” . 提到参数 , 最熟悉的就是定义方法时有形参 , 然后调用方法传递实参 . 那么参数化类型如何理解? 就是将类型由原来具体的类型参数化 , 类似于方法中的变量参数 , 此时类型也定义成参数形式 , 然后在调用的时候传入具体的类型 .下面采用泛型后, 当通过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基础学习总结(82)——Java泛型实例教程
- 黑马程序员---java泛型学习总结
- Java基础学习总结(82)——Java泛型实例教程
- java泛型学习-自定义泛型方法与类型推断总结
- Java学习总结第三十天Java泛型(三)
- Java泛型学习总结
- Java基础学习总结(83)——Java泛型总结
- 结合本人学习,总结一些C#和JAVA的不同这处
- 软件工程学习总结
- 前一段时间的学习总结
- 我的学习总结
- good,JSP学习经验总结
- 老猫的ASP.NET学习总结
- 学习ejb并配置一个简单的helloEjb是遇到问题后总结的经验。
- 一些C++连接,以及个人的C++学习总结。
- VC实例学习 (1):总结下今天学习的东西
- 2001 Microsoft Tech Ed (Beijing 2001/9/7 – 2001/9/9)学习总结
- 在自己学习stuts是遇到问题后总结的经验。
- 蛙蛙推荐:蛙蛙学习asp.net总结(之一)