Java泛型深入探讨:类型安全的编程实践

大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

Java泛型是Java 5引入的一项功能,它允许在编译时进行类型检查,从而提高代码的复用性和类型安全性。泛型通过参数化类型来实现,使得同一段代码可以用于不同的数据类型。

泛型基础

泛型可以应用于类、接口和方法。

public class GenericClass<T> {
    private T data;

    public void setData(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}

public interface GenericInterface<T> {
    void add(T data);
    T get(int index);
}

public class GenericMethod {
    public <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

类型参数

类型参数可以是类类型、接口类型或者通配符类型。

public class Box<T> {
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Box<Integer> integerBox = new Box<>();
integerBox.set(123);
Integer i = integerBox.get();
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

泛型类

泛型类可以定义泛型类型参数。

public class Stack<T> {
    private T[] stackArray;
    private int size = 0;
    private static final int DEFAULT_SIZE = 16;

    public Stack() {
        stackArray = (T[]) new Object[DEFAULT_SIZE];
    }

    public void push(T t) {
        ensureCapacity();
        stackArray[size++] = t;
    }

    public T pop() {
        if (size == 0) throw new EmptyStackException();
        T t = stackArray[--size];
        stackArray[size] = null; // help GC
        return t;
    }

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

    private void ensureCapacity() {
        if (size == stackArray.length) {
            T[] oldArray = stackArray;
            stackArray = (T[]) new Object[2 * size + 1];
            System.arraycopy(oldArray, 0, stackArray, 0, size);
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

泛型方法

泛型方法可以定义在类中,也可以定义在接口中。

public class Utils {
    public static <K, V> void put(Map<K, V> map, K key, V value) {
        map.put(key, value);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

泛型接口

泛型接口可以定义泛型类型参数。

public interface BinaryTree<T> {
    void add(T data);
    T getMax();
}
  • 1.
  • 2.
  • 3.
  • 4.

泛型的继承

泛型类型可以扩展泛型类型。

public 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 first; }
    public T getSecond() { return second; }
}

Pair<Integer> pair = new Pair<>(1, 2);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

泛型的通配符

通配符?可以代表任何类型。

public class GenericWildcard {
    public static void main(String[] args) {
        List<? extends Number> numberList = new ArrayList<>();
        numberList.add(new Integer(10));
        // numberList.add("String"); // 编译错误
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

泛型的类型擦除

Java泛型在编译时会被擦除,转换为它们的边界或Object。

public class Erasure {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        List<Integer> intList = new ArrayList<>();
        List<?> rawList = new ArrayList<>();
        
        List rawList2 = List.class.cast(rawList);
        List rawList3 = (List) rawList;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

泛型与数组

泛型数组在Java中是非法的。

public class GenericArray {
    public static void main(String[] args) {
        // T[] array = new T[10]; // 编译错误
        // 正确的方式
        Integer[] intArray = new Integer[10];
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

泛型的限制

泛型有一些限制,比如不能实例化泛型类型。

public class GenericLimitations {
    public static void main(String[] args) {
        // T t = new T(); // 编译错误
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

泛型与反射

泛型与反射结合使用时,需要注意类型擦除的问题。

import cn.juwatech.util.reflect.ReflectionUtils;

public class GenericReflection {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("cn.juwatech.util.reflect.GenericClass");
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

泛型的实际应用

泛型在集合框架、数据库操作、设计模式等方面有广泛应用。

import cn.juwatech.util.collections.ArrayList;

public class GenericApplication {
    public static void main(String[] args) {
        ArrayList<String> stringList = new ArrayList<>();
        stringList.add("Hello");
        stringList.add("World");
        for (String str : stringList) {
            System.out.println(str);
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

本文著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!