泛型

作者: 咸鱼有梦想呀 | 来源:发表于2017-11-27 17:32 被阅读0次

1.泛型(generic)
泛型:可以按类型进行参数化的类。

2.泛型的好处

  • 将运行时期的问题ClassCastException转到了编译时期。
    也就是
情况演示

但如果控制了类型,在运行时期就可以发现问题

有类型后情况演示
  • 避免了强制转换的麻烦。

  • 提高了编译的安全性。

3.<>使用情况
在操作的引用数据类型不确定的时候。
将要操作引用的数据类型放在<>中就可以。

<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。

<E>

<E>E就是类型变量,类或者是接口。

4.泛型的擦除和补偿

  • 擦除:
    泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
    运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个就称为泛型的擦除。
    擦除的意义在于,为了兼容运行的类加载器。

  • 补偿:
    在运行时,通过获取元素的类型进行转换动作,不用使用者再进行强制转换。

补偿演示

5.泛型类
使用泛型来接收类中要操作的引用数据类型。

泛型类可以自定义,当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。

举个栗子,来说明泛型的作用

首先先建一个Student类,和Worker类,以及一个Tool类,再在另个类中用Tool调用。

Student类代码:

public class Student extends Person {

    public Student() {
        super();
    }

    public Student(String name, int age) {
        super(name, age);
    }

}

Worker类代码:

public class Worker extends Person {

    public Worker() {
        super();
    }

    public Worker(String name, int age) {
        super(name, age);
    }

}

没有泛型之前,如果想操作所有类,就要找所有类的共性
因此,Tool类的代码就要用Object:

public class Tool {

    private Object object;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

另外一个类里用Tool调用
GenericDemo2代码:

import admin.Student;
import admin.Tool;

public class GenericDemo2 {

    public static void main(String[] args) {
        Tool tool = new Tool();
        tool.setObject(new Student());
        Student stu = (Student)tool.getObject();//强转
    }
}

上面这个是可以运行的,但是——接着看:
当调用Worker类的时候,编译环境不报错,但是运行却报错,因为Worker不能强转为Student类。

编译和运行时的区别

但是如果将Tool类,用泛型自定义,这样的错误就会在编译环境显示出来。
泛型类的Tool类代码:

public class Tool<QQ>{
    private QQ q;

    public QQ getQ() {
        return q;
    }

    public void setQ(QQ q) {
        this.q = q;
    }
}

用自定义泛型类调试GenericDemo2:

演示图 省略强转

由此可见,泛型类可以将运行时期会出现的问题转到编译时期。
除此之外还避免了强转的麻烦。泛型类和Object相比较更为安全。

6.泛型方法
将泛型定义到方法上。
当方法静态时,不能访问类上定义的泛型,因为静态是不需要对象的,但是泛型需要对象来明确。
如果静态方法想使用泛型,只能将泛型定义在方法上。

还是延续上一个的栗子
在Tool类中再加几个方法,代码如下:

//泛型自定义到方法上,就会自动找类型匹配。
    public <W> void show(W str){
        System.out.println("show :"+str.toString());
    }
    //和对象一样的泛型
    public void print(QQ str){
        System.out.println("print :"+str);
    }
    //静态方法想使用泛型,要将泛型定义到方法上。
    public static <Y> void method(Y q){
        System.out.println("method :"+q);
    }

用自定义泛型方法调试GenericDemo3:

import admin.Tool;

public class GenericDemo3 {

    public static void main(String[] args) {
        Tool<String> tool = new Tool<String>();
        
        //show方法可以打印任意类型
        //因为在show方法上自定义了泛型
        tool.show(new Integer(4));
        tool.show("abca");
        
        //print方法只能打印字符串
        //因为print的泛型是跟着对象走的
        tool.print("asdf");

                //调用静态方法
        Tool.method("haha");
        Tool.method(new Integer(9));
    }
}
运行结果

使用了泛型,就说明对象不确定,不能使用具体哪个对象的方法,但是具备Object的方法。

7.泛型接口
将泛型定义在接口上。

代码说明:

interface Inter<T>{
    public void show(T t);
}

class InterImp1 implements Inter<String>{
    public void show(String str){
        System.out.println("show :"+str);
    }
}

class InterImp2 <A> implements Inter<A>{
    public void show(A a){
        System.out.println("show :"+a);
    }
}
public class GenericDemo4 {

    public static void main(String[] args) {
        InterImp1 in = new InterImp1();
        in.show("abc");
        
        InterImp2 on = new InterImp2();
        on.show(new Integer(4));
        on.show("abc");
        on.show(2);
    }
}
运行结果

8.泛型的通配符
通通都匹配的符号——未知类型

代码说明:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GenericadvanceDemo {

    public static void main(String[] args) {
        ArrayList<String> a1 = new ArrayList<String>();
        a1.add("abc");
        a1.add("sdcf");
        
        ArrayList<Integer> a2 = new ArrayList<Integer>();
        a2.add(2);
        a2.add(56);
        
        printCollection(a1);
        printCollection(a2);
        
    }
    
    //迭代并打印集合中元素
    public static void printCollection(Collection<?> a){
        Iterator<?> it = a.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}
运行结果

9.泛型限定
对类型的限定

  • 泛型的上限

? extends E

E:接收E类型或者E的子类型对象

举个栗子:
代码:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import admin.Person;
import admin.Student;
import admin.Worker;

public class GenericadvanceDemo {

    public static void main(String[] args) {
        ArrayList<Student> a1 = new ArrayList<Student>();
        a1.add(new Student("lisi",22));
        a1.add(new Student("zhangsan",21));
        
        ArrayList<Worker> a2 = new ArrayList<Worker>();
        a2.add(new Worker("wangwu",33));
        a2.add(new Worker("gongtou",21));
        
        printCollection(a1);
        printCollection(a2);
        
    }
    //迭代并打印集合中元素
    public static void printCollection(Collection<? extends Person> a){
        Iterator<? extends Person> it = a.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next().toString());
        }
    }
}
上述代码运行结果

但是,如果不是Person的子类型就会在编译时报错

泛型上限举例
  • 泛型的下限

? super E

E:接收E类型或者E的父类型对象

举个栗子:
代码:

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import admin.Person;

public class GenericadvanceDemo2 {

    public static void main(String[] args) {
        TreeSet<Person> a1 = new TreeSet<Person>(new CompByName());
        a1.add(new Person("p1",22));
        a1.add(new Person("p3",25));
        a1.add(new Person("acds",20));
        
        Iterator<Person> it = a1.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}
class CompByName implements Comparator<Person>{

    @Override
    public int compare(Person arg0, Person arg1) {
        
        int temp = arg0.getName().compareTo(arg1.getName());
        
        return temp==0? arg0.getAge()-arg1.getAge():temp;
    }
}
运行结果

上限下限的选择
上限:一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患。
下限:通常对集合中的元素进行取出操作时,可以使用下限。

相关文章

  • 泛型 & 注解 & 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/qqksvxtx.html