Java中泛型初探

泛型类

泛型类就是有一个或多个类型变量的类。

package com.studyjava.demo;

import java.util.*;

public class Demo19
{
    public static void main (String[] args)
    {       
        var pair = new Pair<String>("hello ", "java");
        System.out.println(pair.getFirst() + pair.getSecond());
    }
}

class Pair<T>
{
    private T first;
    private T second;

    public Pair (T first, T second)
    {
        this.first = first;
        this.second = second;
    }

    public T getFirst()
    {
        return this.first;
    } 

    public T getSecond ()
    {
        return this.second;
    }

    public void setFirst (T first)
    {
        this.first = first;
    }

    public void setSecond (T second)
    {
        this.second = second;
    }
}

泛型类可以有多个类型变量。例如ClassName<T,U,S>

泛型方法

泛型方法可以在普通类中定义,也可以在泛型类中定义。

package com.studyjava.demo;

import java.util.*;

public class Demo19
{
    public static void main (String[] args)
    {       
        System.out.println(Unit.t("hello"));
        System.out.println(Unit.t(100));
    }
}

class Unit
{
    public static <T> T t (T arg)
    {
        return arg;
    }
}

类型变量的限定

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

class Unit
{
    public static <T> T t (T ...args)
    {
        T item = args[0];

        for (int i=1; i < args.length; i++)
          if (item.compareTo(args[i]) > 0)
            item = args[i];

        return item;
    }
}

该代码会编译失败,这里有个问题,变量args类型为T,这意味着它可以是任何一个类的对象。如何知道T所属的类有一个compareTo方法呢?

解决这个问题的方法是限制T只能是实现了Comparator接口的类。可以通过对类型变量做一个限定:

public static <T extends Comparable> T t (T ...args)

注意,这里使用的是extends关键字,而不是implements。

<T extends BoundingType>表示T应该是限定类型(boundingType)的子类型(subtype)。T和限定类可以是类,也可以是接口。

一个类型变量或通配符可以有多个限定,例如:

T extends Comparable & Clonable

限定类型用&隔开,而逗号用来分割类型变量。

在java的继承中,可以根据需要拥有多个接口超类型,但最多有一个限定可以是类,如果有一个类作为限定,它必须是限定列表中的第一个。

最后,来改写上述方法

package com.studyjava.demo;

import java.util.*;

public class Demo19
{
    public static void main (String[] args)
    {       
        System.out.println(Unit.t(3,23,12));
        System.out.println(Unit.t("php", "java", "c++", "golang", "c#"));
    }
}

class Unit
{
    public static <T extends Comparable> T t (T ...args)
    {
        T item = args[0];

        for (int i=1; i < args.length; i++)
          if (item.compareTo(args[i]) > 0)
            item = args[i];

        return item;
    }
}