加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

让你滔滔不绝的Java的泛 型知识点梳理

发布时间:2022-12-10 11:23:04 所属栏目:语言 来源:
导读:  最近技术交流群里,有朋友问:Object和泛型T有啥区别。回答完问题,不禁在想,面试在即,还有那么多朋友不了泛型?是时候给大家整理一篇泛型相关的文章了,一篇文章全面搞定泛型,让大家再也不愁面试或实践中泛

  最近技术交流群里,有朋友问:Object和泛型T有啥区别。回答完问题,不禁在想,面试在即,还有那么多朋友不了泛型?是时候给大家整理一篇泛型相关的文章了,一篇文章全面搞定泛型,让大家再也不愁面试或实践中泛型相关的问题了。
 
  什么是泛型
 
  泛型是在JDK 5时就引入的新特性,也就是“参数化类型”,通俗来讲就是将原来的具体类型通过参数化来定义,使用或调用时再传入具体的类型(类型实参)。
 
  泛型的本质是为了参数化类型(在不创建新类型的前提下,通过泛型指定的不同类型来控制形参具体的类型)。在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
 
  为什么使用泛型
 
  未使用泛型时,可以通过Object来实现参数的“任意化”,但这样做的缺点就是需要显式的强制类型转换,这就需要开发者知道实际的类型。
 
  而强制类型转换是会出现错误的,比如Object将实际类型为String,强转成Integer。编译期是不会提示错误的,而在运行时就会抛出异常,很明显的安全隐患。
 
  Java通过引入泛型机制,将上述的隐患提前到编译期进行检查,开发人员既可明确的知道实际类型,又可以通过编译期的检查提示错误,从而提升代码的安全性和健壮性。
 
  使用泛型前后的对比
 
  拿一个经典的例子来演示一下未使用泛型会出现的问题。
 
  List list = new ArrayList();
 
  list.add(1);
 
  list.add("zhuan2quan");
 
  list.add("程序新视界");
 
  
 
  for (int i = 0; i < list.size(); i++) {
 
      String value = (String) list.get(i);
 
      System.out.println("value=" + value);
 
  }
 
  上述代码在编译器并不会报任何错误,但当执行时会抛出如下异常:
 
  java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
 
  那么,是否可以在编译器就解决这个问题,而不是在运行期抛出异常呢?泛型应运而生。上述代码通过泛型来写之后,变成如下形式:
 
  List<String> list = new ArrayList<>();
 
  list.add(1);
 
  list.add("zhuan2quan");
 
  list.add("程序新视界");
 
  
 
  for (String value : list) {
 
      System.out.println("value=" + value);
 
  }
 
  可以看出,代码变得更加清爽简单,而且list.add(1)这行代码在IDE中直接会提示错误信息:
 
  Required type: String
 
  Provided: int
 
  提示错误信息便是泛型对向List中添加的数据产生了约束,只能是String类型。
 
  泛型中通配符
 
  在使用泛型时经常会看到T、E、K、V这些通配符,它们代表着什么含义呢?
 
  本质上它们都是通配符,并没有什么区别,换成A-Z之间的任何字母都可以。不过在开发者之间倒是有些不成文的约定:
 
  T (type) 表示具体的一个java类型;
 
  K V (key value) 分别代表java键值中的Key Value;
 
  E (element) 代表Element;
 
  为什么Java的泛型是假泛型
 
  为了做到向下兼容,Java中的泛型仅仅是一个语法糖,并不是C++那样的真泛型。
 
  还是上面的例子,在直接向泛型为String的List中添加int类型会提示错误:
 
  List<String> list = new ArrayList<>();
 
  list.add(1);
 
  针对上述代码,我们采用反射间接地调用add方法:
 
  @Test
 
  public void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
 
      List<Integer> list = new ArrayList<>();
 
      list.add(1);
 
      Method add = list.getClass().getMethod("add", Object.class);
 
      add.invoke(list,"程序新视界");
 
      System.out.println(list);
 
      System.out.println(list.get(1));
 
  }
 
  执行上述代码,我们发现程序并没有抛出异常,正常打印出入:
 
  [1, 程序新视界]
 
  程序新视界
 
  原本只能装入Integer的List,成功装入了一个String类型的值。由此可见,所谓的泛型确实是假泛型。
 

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!