JAVA基础之路——泛型

关于泛型

什么是泛型?

泛型能让数据变得更严格 更不容易出错
这么说有点片面 下面用例子来说明:
Arraylist:动态数组,长度可变的数组。

Arraylist numbers = new Arraylist();
numbers.add(1);
numbers.add(2);
numbers.add("String")
numbers.forEach(System.out::println);

这里,可以看到我们插入了三个数据,但是第三个数据是一个String类型。
但是这样显然不合理,一个数组怎么会有整形又有字符串呢?

但是!让我用泛型来解决这个问题:

Arraylist<Integer> numbers = new Arraylist<>();
numbers.add(1);
numbers.add(2);
numbers.add("String") 
numbers.forEach(System.out::println);

这时,可以看到我们在Arraylist后面加了,这就是泛型的应用。
它给数组规定了类型,当我们再往数组里插入String类型的数据时,程序就会报错。
这就是泛型的优点之一 让数据变得更加严格 更不容易出错!

泛型类

有什么用呢?
当然有用了,它既然是个类型,就可以声明变量。
private E first; //这里的E就是first的类型。

接下来我们用一串代码来做示范:

public class Pair<T> {
    /* Pair类引入了一个类型变量T,用尖括号括了起来。
    *  泛类型可以有多个类型变量。例如 可以定义Pria类,
    */其中 第一个域和第二个域使用不同的类型 Pair<T,F,V....>
    private T first;   //创建了两个变量 
    private T two;

    //此处省略 带参、无参构造器、get、set方法

}

再创建一个类

class ArrayAlg{  //用来写一个方法
    public static Pair<String> minmax(String[] a){  //调用泛型类来创造一个方法 用来比较字符串的大小
        //注意,这时Prai<>这个尖括号中 就已经规定类型了 为String
        if (a == null || a.length == 0) return  null; //若数组的长度为0直接返回空
        String min,max;
        min = max = a[0];
        for (int i = 1 ; i < a.length ; i++) {
            if (min.compareTo(a[i])>0) min = a[i];
            if (max.compareTo(a[i])<0) max = a[i];
        }
        return new Pair<>(min,max);     //返回值的泛型语法,这时尖括号中已经不用再次写类型了。
    }
}

接下来 测试一下:

public class PairTest {
    public static void main(String[] args) {   
        String[] words = {"Mary","Litter","Ben","asfas","AFASafs"}; //给出一个数组
        Pair<String> mm = ArrayAlg.minmax(words); // 把数组参数送到方法中   进行比较
        System.out.printf("%s  $s",mm.getFirst(),mm.getTwo());
    }
}

这时,大概就知道泛型的好处了,为什么这么说?
因为如果我还要做一个方法,用来比较另外一组数据,我可以在最上面的类中加入另一个
变量类型 例如:Pair

泛型方法

值得一提的是 和抽象类还有抽象方法不一样
泛型类和泛型方法没有联系 上面例子中的方法 只是一个普通的方法
泛型方法主要提供了一种操纵数据的方法 就好比要取一个数组中好多元素的中间的那个,如果没有泛型,就要重载好多方法。
再用代码来解释:

public static <T> T getMiddle(T...a){  //泛型方法的写法<T>
        return a[a.length/2];
    }

注意这里我们并没有给这个方法的参数规定类型,下面,我们调用这个方法试一试:

System.out.println(ArrayAlg.getMiddle("asda","dasd","sadasd");
System.out.println(ArrayAlg.getMiddle("1","2","3");

还可以举很多例子,各种类型都可以。那么泛型方法的有点在哪呢?
如果我们不适用泛型:

public static int T getMiddle(int...a){  //泛型方法的写法<T>
        return a[a.length/2];
    }

System.out.println(ArrayAlg.getMiddle("1","2","3");
//可以看到,这个方法只能用int类型的数据。
public static int String getMiddle(String...a){  //泛型方法的写法<T>
        return a[a.length/2];
    }

System.out.println(ArrayAlg.getMiddle("asda","dasd","sadasd");

而这个方法只能用String类型的数据
每当你想用不同类型的数据去参与运算,你就得不停的去重载方法。非常麻烦!

类型变量的限定

有时,类或方法需要对类型变量加以约束,下面的例子中,我们要计算数组中的最小元素

 public static <T> T min(T[] a) {
        if(a == null || a.length == 0) return null;
        T smallest = a[0];
        for(int i = 1; i < a.length; i++)
            if(smallest.compareTo(a[i]) > 0) smallest = a[i];   
                return smallest;                                
    }

你会发现,当你写到第五行的时候 就会报错,因为compareTo方法必须
是在有comparebo接口的情况下才能使用的。
那要怎么办呢?
答:让继承comparebo接口!!!
下面正确代码:

public static <T extends & Comparable> T min(T[] a) {
        if(a == null || a.length == 0) return null;
        T smallest = a[0];
        for(int i = 1; i < a.length; i++) 
            if(smallest.compareTo(a[i]) > 0) smallest = a[i];
        return smallest;
    }

这样就可以了。
关于类型变量的限定 需要注意以下几点:
1.泛类型可以继承多个接口,但是标记性接口一定要放在最后。
2.泛类型要继承类的时候,一定要让类放在最前面。

以上所学为个人总结。难免不严谨,见谅!

猜你喜欢

转载自blog.csdn.net/weixin_42825755/article/details/81913257