java泛型

什么时java泛型?

泛型时jdk1.5版本以后出现的一种对类、方法、接口的一种类型的约束,这种类型的约束是存在与编译时期的一种约束,在程序的运行时期是没有泛型的运用。

泛型的作用只存在与代码的编译时期,运行时没有泛型的存在

泛型即"参数化类型"

就是将对象将参数传递,为了能够更好的理解泛型,我们以上一篇中的分页工具类来解释,代码如下:

package com.zs.util;

import com.zs.entity.User;

import java.util.List;

public class PageUtil {
    private int firstPage;
    private int proPage;
    private int currentPage;
    private int nextPage;
    private int lastPage;
    private List<User> list;

    public PageUtil() {

    }
    
    public PageUtil(int currentPage,int countPage, List<User> list) {
        this.firstPage = 1;
        this.currentPage = currentPage;
        this.lastPage = countPage;
        this.proPage = this.currentPage == 1 ? 1 : (this.currentPage - 1);
        this.nextPage = this.currentPage == this.lastPage ? this.currentPage : this.currentPage + 1;
        this.list = list;
    }

    public int getFirstPage() {
        return firstPage;
    }

    public void setFirstPage(int firstPage) {
        this.firstPage = firstPage;
    }

    public int getProPage() {
        return proPage;
    }

    public void setProPage(int proPage) {
        this.proPage = proPage;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getNextPage() {
        return nextPage;
    }

    public void setNextPage(int nextPage) {
        this.nextPage = nextPage;
    }

    public int getLastPage() {
        return lastPage;
    }

    public void setLastPage(int lastPage) {
        this.lastPage = lastPage;
    }

    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }
}
View Code

这是上一篇中我们写的分页栏的工具,当我们在前台点击了下一页等跳转按钮后,就会发送一个页数的请求到后台,后台将传递过来的页数作为当前页,然后获取当前页的数据信息,并存入一个集合中,然后通过分页类的构造方法计算上一页,下一页等信息,并将当前页的信息一并存入工具类里了。

上一篇里例子中,我们只创建了一个用户的类,只读取了user表的数据,那么如果现在有一个person表,我们要获取person表的内容,在一系列操作后获取了当前页的内容,我们要存入List<Person>类型的list中,但是我们的分页类PageUtil内的list是一个List<User> 类型的,这样就出现了类型的不一致,但是分页的代码都是一样的,我们不能因为这个小原因,重新创建类,因此我们就会想,我们能不能将这个List内的类型当作参数传递过去呢,我们调用方法时,写的是什么类型,那么类内部的List就是什么类型。

这种将对象作为参数传递的行为就是泛型。

还是前面的pageUtil类,在没有用泛型时,现在只能传递User为类型的list,那么我们将它进行改造成泛型。

package com.zs.util;

import java.util.List;

public class PageUtil<T> {
    private int firstPage;
    private int proPage;
    private int currentPage;
    private int nextPage;
    private int lastPage;
    private List<T> list;

    public PageUtil() {

    }

    public PageUtil(int currentPage,int countPage, List<T> list) {
        this.firstPage = 1;
        this.currentPage = currentPage;
        this.lastPage = countPage;
        this.proPage = this.currentPage == 1 ? 1 : (this.currentPage - 1);
        this.nextPage = this.currentPage == this.lastPage ? this.currentPage : this.currentPage + 1;
        this.list = list;
    }

    public int getFirstPage() {
        return firstPage;
    }

    public void setFirstPage(int firstPage) {
        this.firstPage = firstPage;
    }

    public int getProPage() {
        return proPage;
    }

    public void setProPage(int proPage) {
        this.proPage = proPage;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getNextPage() {
        return nextPage;
    }

    public void setNextPage(int nextPage) {
        this.nextPage = nextPage;
    }

    public int getLastPage() {
        return lastPage;
    }

    public void setLastPage(int lastPage) {
        this.lastPage = lastPage;
    }

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }
}
View Code

现在这个工具类,就可以保存各种类型的数据集合了,我们可以创建多个类型来测试看能不能放进去。这里因为还要写泛型的应用,就不做测试了。

泛型的应用:

1.泛型类

package com.zs.service;

/**
 * 泛型的类型类似于object类,什么类型都可以,但是不可以使用八大基本类型int、double...,
 * 如果使用八大基本类型的数据,要使用包装类Integer、Double...
 * 泛型定义在类上public class 类名<泛型类型1,..>可以定义多个泛型类型
 * @param <E>
 */
public class Demo1<E> {

    private E e;

    public E getE() {
        return e;
    }

    public void setE(E e) {
        this.e = e;
    }
}

这样就创建了一个简单的泛型类。e可以是任意类型,还可以传递多个类型:

package com.zs.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 泛型的类型:T:type  E:element K:key V:value这些都指代类型,没有区别
 * @param <E>
 * @param <K>
 * @param <Y>
 */
public class Demo2<E,K,Y> {
    private List<E> e;
    private HashMap<K,Y> map;

    public List<E> getE() {
        return e;
    }

    public void setE(List<E> e) {
        this.e = e;
    }

    public HashMap<K, Y> getMap() {
        return map;
    }

    public void setMap(HashMap<K, Y> map) {
        this.map = map;
    }

}

可以看出,在创建demo的对象是,声明了list的类型为string类型,因此list只能放string类型,如果存放integer类型会报错,同样的demo2里的hashmap的数据类型为string,integer

在创建对象时,会根据实力化对象时的类型,自动填充内部的E,K,V等,按照顺序填充。

2.泛型方法

package com.zs.service;

public class Demo3 {
    /**
     * 泛型方法的参数类型可以是任意类型的,但是在声明方法时,要在返回值前声明这是个泛型方法<T>
     * @param t
     * @param <T>
     */
    public <T> void fun1(T t) {
        System.out.println("方法执行了" + t);
    }

    public static void main(String[] args) {
        Demo3 demo3 = new Demo3();
        demo3.fun1("字符串");
        demo3.fun1(111);
        demo3.fun1(true);
        /**
         * 运行结果,可以看到fun内可以传任意类型参数
         */
    }
}

3.泛型接口

package com.zs.service;

/**
 * 如果一个类实现了泛型接口,那么这个类必须得到泛型
 * @param <T>
 */
public class Demo4Impl<T> implements Demo4<T> {
    @Override
    public void fun(T t) {
        System.out.println("执行了" + t);
    }

    public static void main(String[] args) {
        Demo4<String> demo4 = new Demo4Impl<>();
        /*上面声明了泛型类型为string类型,因此fun只能传string类型参数*/
        demo4.fun("111");
    }
}

泛型的作用:

  1.提高了程序的安全性(泛型在集合里的使用)
  2.将运行期遇到的问题,提前到了编译期

  3.省去了代码强转的麻烦

  4.提高了代码的重用性,实现代码的公共的封装

泛型的高级应用:

  1.泛型通配符<?>

  2.<? extends E>

    向下限定,E及其子类

  3.<? supper E>

    向上限定,E及其父类

举例说明:

package com.zs.service;

import java.util.List;

public class Demo5 {
    /**
     * 通配符类型传参,相当于object,可以传任意类型
     * @param list
     */
    public void fun1(List<?> list) {
        System.out.println(list);
    }

    /**
     * list的类型可以是demo3或其所有子类类型的
     * @param list
     */
    public void  fun2(List<? extends Demo3> list) {
        System.out.println(list);
    }

    /**
     * list的类型可以是demo3或其父类类型的
     * @param list
     */
    public void fun3(List<? super Demo3> list) {
        System.out.println(list);
    }
    
}
原文地址:https://www.cnblogs.com/Zs-book1/p/11127502.html