Java中的泛型是什么?

  • Post category:Java

Java中的泛型是一种强类型参数化的机制,它允许类、接口、方法在定义时使用一个或多个类型变量,这些类型变量随后用于指定类、接口、方法中的类型。泛型在Java中的引入是为了提升代码的重用性、类型安全以及程序的可读性和可维护性。

如何定义和使用泛型

Java中定义泛型的的语法是:在类型名称后添加尖括号(<>),在其中声明一个或多个泛型类型参数。如下所示:

public class MyClass<T> {
    private T myField;

    public MyClass(T initialVal) {
        myField = initialVal;
    }

    public T getValue() {
        return myField;
    }
}

上述代码中,我们定义了一个名为MyClass的泛型类,该类的类型参数为T。类中有一个名为myField的私有变量,类型为T,构造方法中需要传入参数initialVal,并利用赋值语句将它赋值给myField变量。另外,该类还有一个名为getValue()的公共方法,它返回myField变量的值,并声明了T类型作为方法的返回类型。

我们可以使用MyClass类型创建一个对象。但是,在创建时需要指定myField变量的实际类型。如下所示:

MyClass<Integer> myObj = new MyClass<Integer>(42);

在上述代码中,我们创建了一个名为myObj的MyClass对象,并将42作为构造函数的参数,该对象的类型为MyClass\<Integer>,用来表示myField变量应该是一个整数类型。

使用泛型后,我们可以在运行时获得更强的类型检查,从而降低了类型转换错误的风险。

示例

示例1:使用泛型实现栈

下面的代码会演示使用泛型来实现一个简单的栈(stack)类,并使用它存储字符串对象。

class MyStack<T> {
    private T[] stackArray;
    private int stackSize;

    public MyStack(int size) {
        stackArray = (T[]) new Object[size];
        stackSize = 0;
    }

    public void push(T element) {
        stackArray[stackSize++] = element;
    }

    public T pop() {
        return stackArray[--stackSize];
    }

    public boolean isEmpty() {
        return stackSize == 0;
    }
}

public class Main {
    public static void main(String[] args) {
        MyStack<String> stack = new MyStack<String>(10);
        stack.push("hello");
        stack.push("world");

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }
}

在上述代码中,我们定义了一个MyStack类,该类使用了类型参数T表示栈中存储的元素的类型。在构造函数中创建了一个数组,用于存储元素,并且定义了入栈(push),出栈(pop)和判断是否为空(isEmpty)的方法。

我们使用MyStack\<String>类型进行创建对象,并对该对象进行push操作。因为我们设置了泛型的类型,所以我们只能对该对象压入字符串类型的值。在使用pop方法弹出元素时,由于数据类型正确,所以无需进行类型转换。

示例2:通过继承泛型类型实现缩减代码

下面的代码演示了如何继承泛型类型,从而减少代码量。

class MyList<T> {
    private ArrayList<T> innerList = new ArrayList<T>();

    public void add(T value) {
        innerList.add(value);
    }

    public ArrayList<T> getList() {
        return innerList;
    }
}

class MyStringList extends MyList<String> {
    public String getFirstElement() {
        return getList().get(0);
    }
}

public class Main {
    public static void main(String[] args) {
        MyStringList list = new MyStringList();
        list.add("hello");
        list.add("world");

        System.out.println(list.getFirstElement());
    }
}

在上述代码中,我们定义了一个MyList类,它是一个泛型类,并且有一个内部的ArrayList集合,用于存储元素。MyStringList类继承了MyList类,并通过对类型参数的具体化实现,重载了ArrayList来实现字符串的存储。

在例子中,我们创建了一个MyStringList的实例,并将两个字符串添加到列表中。然后,我们调用getFirstElement()以获取第一个元素并将其输出到控制台。

通过继承MyList类型,我们成功地缩减了代码量,避免了将相同的代码重复使用在不同类型上的情况。