泛型

作者: 东风谷123Liter | 来源:发表于2018-09-17 19:24 被阅读0次

Java1.5之后出现的类型安全机制;

好处:

  • 运行时期出现的ClassCastExcepton异常,转换到编译时期。方便程序员解决问题,安全!
  • 避免类型强转带来的麻烦。

格式:

  • 通过<>来定义要操作的类型。

什么时候使用:

  • 集合框架中常用。
  • 自定义泛型类,当类中要操作的数据类型不确定时,早期用Object来完成;现在定义泛型类就可以完成。

用的地方:

  • 除了可以定义在类上,也可以定义在方法上。写法都差不多:在类名后面加上<T>表T类型;其中T也可以用别的字母代替。
  • 方法上只不过是将T作为参数传递进去就OK。
  • 用了泛型的方法,传啥都行,不用指定参数类型。

泛型的缺点:

  • 如果泛型定义在类上,那么该类中的方法都得用同一种数据类型参数,这程序设计有很大的局限性。
  • 于是我们可以直接把类型定义在方法上,格式:在返回值类型前面加上 <T>就可以了;原理就是把T类型的作用域减小。

注意:

  • 静态方法不可以使用类上定义的泛型;如果想在静态方法上使用泛型,可以直接在静态方法上定义泛型;在返回值类型前面加上<T>就OK。这时就不用类上定义的是什么泛型!
  • 我们也可以用通配符<?>来代替<T>;但这种情况有一个要求,就是类或方法里面没有出现T t=....;这样的定义。

泛型的高级应用:

  • 代码如下:
public static void main(String[] args) {
           ArrayList<String> al1 = new ArrayList<String>();
           al1.add("abc");
           al1.add("djhf");
           al1.add("djhf01");
           al1.add("djhf02");
           ArrayList<Integer> al2 = new ArrayList<Integer>();
           al2.add(3);
           al2.add(4);
           al2.add(5);
           al2.add(6);
     }
  • 此时如果我们想打印这两个数组集合,我们就得定义两个迭代器。
  • 这似乎做了重复工作;
  • 此时,我们可以利用泛型的高级引用来解决!
  • 我们可以定义一个方法,来封装这个迭代器。
     public static void printIterator(ArrayList al) {
           Iterator it = al.iterator();
           while(it.hasNext()) {
                System.out.println(it.next());
      }
  • 调用封装好的迭代器
       printIterator(al1);
       printIterator(al2);
  • 打印结果:

问题:

printIterator方法中,并没有指定迭代器的数据类型,为什么也能打印成功?**

因为Java1.4版本之前没有泛型,Java1.5之后为了兼容之前的版本,此处参数传递时不指定数据类型也是可以的;但你这样数据类型不太安全。

还可以这样写:**

public static void printIterator(ArrayList<?> al) {
           Iterator<?> it = al.iterator();
           while(it.hasNext()) {
                System.out.println(it.next());
           }
  • 结果当然一样的,其中<?>中的“?”是通配符;指任意类型!虽然数据安全问题解决了,但是这就意味着任何数据类型这个迭代器都能迭代,范围太大。
  • 我们也可以这样:
public static <T> void printIterator(ArrayList<T> al) {
           Iterator<T> it = al.iterator();
           while(it.hasNext()) {
                System.out.println(it.next());
           }
     }
  • 虽然这和用通配符“?”没什么区别,但这个在方法的内部可用T数据类型来定义引用。
  • 注意:如果我们想调用length()方法,来打印上面两种数据类对象的长度,用<?>或<T>或啥都不指明是无法是实现的,因为Integer类型没有该方法。这里就必须指定数据类型,这也是泛型的缺点。

泛型的限定:

要想灵活的利用好泛型,泛型限定就是最好的选择。

上限;<?> extends T
下线;​<?> super T

  • 现在有一个Person01类,他有一个子类Student01。现在要为他们两封装一个打印方法sopp(),该如何实现呢?
class Person01{
     private String name;
     private int age;
     Person01(String n, int a){
           this.name = n;
           this.age = a;
     }
    public String getName() {
           return name;
     }
     public int getAge() {
           return age;
     }
}
//Student01继承Person01类
class Student01 extends Person01{
     Student01(String n, int a){
           super(n, a);
     }
}
  • 打印方法:
public static void sopp(Person01 p) {
           System.out.println(p.getName()+"..."+p.getAge());
     }
}
  • 定义集合:
public static void main(String[] args) {
           ArrayList<Person01> al = new ArrayList<Person01>();
           al.add(new Person01("lily", 12));
           al.add(new Person01("Tom", 44));
           al.add(new Person01("Litre", 22));
           al.add(new Person01("Greson", 52));
           for(int i=0; i<al.size(); i++) {
                sopp(al.get(i));
           }
     }
  • 结果:


  • 此时参数类型是Person01,且集合类型也是Person01,所以就打印成功了。如果集合是Student01的话编译就会报错,因为类型不匹配。为了让Student01类型的集合也能调用这个方法,我们就要用到泛型限定的向上限定。

public static void sopp(ArrayList<? extends Person01> al) {
           Iterator<? extends Person01> it = al.iterator();
           while(it.hasNext()) {
                System.out.println(it.next().getName());
           }
     }
  • 调用该方法:
sopp(al);
  • 结果:


  • 我们定义一个Student01类型集合,看sopp()能不能打印?
ArrayList<Student01> al1 = new ArrayList<Student01>();
           al1.add(new Student01("lily0001", 12));
           al1.add(new Student01("Tom0001", 44));
           al1.add(new Student01("Litre0001", 22));
           al1.add(new Student01("Greson0001", 52));
           sopp(al1);
  • 结果:


  • 可知Student01类型完全OK。这便是泛型的向上限定,向下先订也是一样的,就不做展示。
  • 好多方法里面就有​<? super E>,<? extends E>比如比较器:Comparator以及compareTo()都有用到。



相关文章

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

  • 【泛型】通配符与嵌套

    上一篇 【泛型】泛型的作用与定义 1 泛型分类 泛型可以分成泛型类、泛型方法和泛型接口 1.1 泛型类 一个泛型类...

  • 泛型的使用

    泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法 泛型类 泛型接口 泛型通配符 泛型方法 静态方法与...

  • Java 泛型

    泛型类 例如 泛型接口 例如 泛型通配符 泛型方法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型上下边...

  • 探秘 Java 中的泛型(Generic)

    本文包括:JDK5之前集合对象使用问题泛型的出现泛型应用泛型典型应用自定义泛型——泛型方法自定义泛型——泛型类泛型...

  • Web笔记-基础加强

    泛型高级应用 自定义泛型方法 自定义泛型类 泛型通配符? 泛型的上下限 泛型的定义者和泛型的使用者 泛型的定义者:...

  • 重走安卓进阶路——泛型

    ps.原来的标题 为什么我们需要泛型? 泛型类、泛型接口和泛型方法(泛型类和泛型接口的定义与泛型方法辨析); 如何...

  • Kotlin泛型的高级特性(六)

    泛型的高级特性1、泛型实化2、泛型协变3、泛型逆变 泛型实化 在Java中(JDK1.5之后),泛型功能是通过泛型...

  • Java 19-5.1泛型

    泛型类定义泛型类可以规定传入对象 泛型类 和泛型方法 泛型接口 如果实现类也无法确定泛型 可以在继承类中确定泛型:

  • 【Swift】泛型常见使用

    1、Swift泛型4种 泛型函数泛型类型泛型协议泛型约束 2、泛型约束3种 继承约束:泛型类型 必须 是某个类的子...

网友评论

      本文标题:泛型

      本文链接:https://www.haomeiwen.com/subject/hafdnftx.html