43-咸鱼学Java-泛型编程

简介

泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。

泛型的使用

先将之前写过的栈转换为泛型栈

/**
 * 泛型栈
 * @author 14831
 *
 * @param <T>
 */
public class TStack<T> {
    /**
     * 泛型数组
     */
    private T[] data = null;
    /**
     * 栈顶
     */
    private int top;
    /**
     * 栈的长度
     */
    private int length;
    /**
     * 空构造函数
     */
    public TStack() {
        this(10);
    }
    /**
     * 有参构造函数
     * @param i 栈的长度
     */
    public TStack(int i)
    {
        //data = new T[i];  × 错误
        length = i;
        //通过将object数组强转为泛型数组的方式创造泛型数组
        data = (T[]) new Object[length];
        //栈顶初始化
        top = 0;
    }
    /**
     * 入栈
     * @param val
     */
    public void push(T val)
    {   
        if(top>=length)
        {
            return;
        }
        this.data[top++] = val;
    }
    /**
     * 出栈
     * @return 数据
     */
    public T pop()
    {   
        if(top==0)
        {
            return null;
        }
        return this.data[--top];
    }
    /**
     * 获得栈顶元素
     * @return 数据
     */
    public T getTop()
    {   if(top==0)
        {
        return null;
        }
        return this.data[top-1];
    }
    public static void main(String[] args) {
        TStack<Integer> a = new TStack<Integer>(10);
        for (int i = 0; i < a.length; i++) {
            a.push(i);
        }
        for (int i = 0; i < a.length; i++) {
            System.out.print(a.pop()+" ");
        }
    }
}

运行结果9 8 7 6 5 4 3 2 1 0
此泛型栈可以根据类型存放不同的对象。

泛型的意义

<T> T是一个类型占位符,它所占的位置就是当你确定这个泛型的类型之后,系统进行自动类型检查和自动类型转换所确定的类型
a.会对类型进行自动检查
b.会进行自动类型转换

泛型的坑

1.不能new泛型类型的数组
正确的方式是这种
data = (T[]) new Object[length];
2.不能new泛型的对象
因为T只是在编译的时候进行类型的检查
3.不能得到泛型类型的对象数组
TStack<Integer>[] a = new TStack<Integer>[10]; ×错误
因为泛型本质是向上擦除成Object,所以其数组相当于Object数组,而且其没有泛型的约束,所以会产生矛盾。
TStack<Integer>[] a = new TStack<Integer>[10];===Object[] a = new Object[10];
然后就可以给a赋任何值,所以其泛型也就没有了意义,此点和泛型的作用(编译类型检查)相矛盾
4.简单类型不能作为泛型的参数
int,double,float等
5.在Static方法中,不能用泛型类型的参数

public static T getT()
    {
        return null;
    }

错误,其正确方式为

    public static<T> T getT()
    {
        return null;
    }

只有在static后面加上<T>编译器才能通过

泛型的上界

泛型的实质是类型擦除,擦除的最终目标是Object,当我们给泛型设定上界以后,泛型就会被擦除成你所指定的上界。其声明方式为

<T extends superClass>

这样就有了无限可能。
我们可以写一个FindMax函数,可以查找所有实现Comparable接口的类的最大值.

/**
 * 寻找最大值
 * @author 焦焱
 *
 * @param <T> Comparable<T>擦除到Comparable<T>
 */
class MyMath<T extends Comparable<T>>
{
    /**
     * 寻找最大值
     * @param array 数组
     * @return      最大的数据
     */
    public static<T extends Comparable<T>> T finMaxVal(T[] array)
    {
        T maxVal = array[0];
        for (int i = 1; i < array.length; i++) {
            if(maxVal.compareTo(array[i])<0)
            {
                maxVal = array[i];
            }
        }
        return maxVal;
    }
}

测试

    Integer[] a = {12,3125,435,64000,67};
    MyMath<Integer> a1 = new MyMath<Integer>();
    System.out.println(a1.finMaxVal(a));

Integer内部已经实现了Comparable接口。
结果64000

泛型没有下界

猜你喜欢

转载自blog.csdn.net/qq_38345606/article/details/80515421