泛型

泛型的好处

  • 提供了一种类型安全检测机制
  • 提升程序可读性

通配符

通配符的出现是为了指定泛型中的类型范围。

通配符有 3 种形式。

  • <?>被称作无限定的通配符。
  • <? extends T>被称作有上限的通配符。
  • <? super T>被称作有下限的通配符。

? 其实代表的是未知类型,所以涉及到 ? 时的操作,一定与具体类型无关。

img

有人说,<?>提供了只读的功能,也就是它删减了增加具体类型元素的能力,只保留与具体类型无关的功能。它不管装载在这个容器内的元素是什么类型,它只关心元素的数量、容器是否为空?我想这种需求还是很常见的吧。

有同学可能会想,<?>既然作用这么渺小,那么为什么还要引用它呢? 

个人认为,提高了代码的可读性,程序员看到这段代码时,就能够迅速对此建立极简洁的印象,能够快速推断源码作者的意图。

类型擦除

在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 <T>则会被转译成普通的 Object 类型,如果指定了上限如 <T extends String>则类型参数就被替换成类型上限。

类型擦除带来的局限性

img

正常情况下,因为泛型的限制,编译器不让最后一行代码编译通过,因为类似不匹配,但是,基于对类型擦除的了解,利用反射,我们可以绕过这个限制。

那么,利用反射,我们绕过编译器去调用 add 方法。

public class ToolTest {


  public static void main(String[] args) {
    List<Integer> ls = new ArrayList<>();
    ls.add(23);
//		ls.add("text");
    try {
      Method method = ls.getClass().getDeclaredMethod("add",Object.class);
      
      
      method.invoke(ls,"test");
      method.invoke(ls,42.9f);
    } catch (NoSuchMethodException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
    for ( Object o: ls){
      System.out.println(o);
    }
  
  }

}

参考链接

Java 泛型,你了解类型擦除吗?

版权

评论