Java 泛型

来源:互联网 发布:erp软件系统 报表 编辑:程序博客网 时间:2024/05/22 11:23

泛型即为类、方法、变量等提供“类型参数”,都是使用<>包括起来。意思是告诉系统我需要定义一些类型参数了,接下来我会使用这些类型参数。基础知识不再详细列出,仅列出一些值得注意和较难理解的问题。

  • 为什么要使用泛型?
    Java中,使用泛型最主要的原因是增加类型的安全性,以及简化代码避免显式的强制类型转换。 从性能上说Java泛型并没有加快,这里涉及到运行时擦除概念和编译器默认加入的类型转换。 所以说Java中的主要作用就是增加安全和简化代码。

  • 不同的类型参数用逗号分隔<T,S extends List>,S表示其是List的子类型。 如果泛型S要同时进行继承和接口的限制,那么需要把继承类写在第一位,如<S extends ClassName & interfaceName1 & interfaceName2>。另外在类上面的泛型编码一般不会使用限制符,影响扩展。

  • 因为运行时擦除的原因,下面两个方法并不是普通的方法重载,而就是同一个方法,编译器是会报错的。

public void go(List<String i){}public void go(List<Integer i){}

也因为运行时擦除,所以使用instanceof这种实例级别的语法去校验是不对的,因为擦除了泛型还如何去校验呢。同理,比较两个泛型对象的getClass显然应该得到相等的结果。

  • 容易晕头的通配符使用。集合类型中的?和? extends方式,是可以赋值的,但是不能add任何非null对象。原因是我们在直接赋值的时候保证了整个集合是同一个类型的。但是在add的时候我们无法知道add进去的类型是否和集合中已经存在的类型是同一类型(虽然都是shape的子类)。这样就会产生问题。
List<? extend Shape> l = new ArrayList<Circle>();//赋值时必须是Shape的子类l.add(new Object());//error!!只要不是null,全都是错误的

集合中? super方式,也是可以赋值的,但是赋值时必须的Shape的超类。同时这种形式允许add,add的是Shape的子类,因为这样肯定可以的知道这个元素至少可上溯造型至shape,如果是Shape的超类就不行了,原因和extends类似。

List<? extend Circle> l = new ArrayList<Shape>();//只要是Circle的超类都可以赋值,赋值时保证了集合中的元素是同一种类型。l.add(new Circle());l.add(new SubCircle());//只要是Circle的子类,就一定能上溯造型成Circle甚至是在赋值语句中Circle的超类。l.add(new Circle某超类());//error!!类似extends,因为并不知道集合内有没有其它的超类
  • 何时使用extends何时使用super,可以遵循PECS原则,即如果你是泛型对象的提供者、生产者,那你身上应该使用extends。 如果你是泛型对象的消费者,那你身上应该使用super。

  • 泛型数组是不合法的,记住不要这么用(除非通配符)。

  • 借用泛型可以让一个集合里拥有很多不同类型的对象各一个,其实是借助了泛型化的Class作为key。Map<Class<?>,Object>。

0 0
原创粉丝点击