Java泛型

发布于:2025-03-01 ⋅ 阅读:(11) ⋅ 点赞:(0)

Java中泛型是什么

总的来讲泛型就是将数据类型参数化,在编写泛型类的时候使用符号占位,在实际使用泛型类的时候,传入需要的数据类型,这里的数据类型不能是基本数据类型,必须是包装类,编译时会自动进行类型的转换。

一.引入

先来假设一个场景,当你需要一个整形打印机时:

public class Printer {
    Integer youWant;

    public Printer(Integer youWant){
        this.youWant = youWant;
    }

    public void print(){
        System.out.println(this.youWant);
    }

    public static void main(String[] args) {
        Printer printer1 = new Printer(20);
        printer1.print();
        
    }
}

输出结果:在这里插入图片描述

这个打印机只能作为整型这个类型的打印机,那么当你需要打印其他类时又要重写那个类专属的Printer,也就是说你每需要一个数据类型的Printer,就需要重新写一个类,而这些类之间仅仅是使用的数据类型不同,代码逻辑和实现的功能都是一样的,这大大降低了开发效率。

此时就需要引入泛型,简单来说泛型是将类中所需要的数据类型泛化,即在编写代码时不将需要经常更改数据类型的那些字段的数据类型定死,使用泛型后,Printer可以写为这样:

public class Printer<T> {
    T youWant;

    public Printer(T youWant){
        this.youWant = youWant;
    }
    
    public void print(){
        System.out.println(this.youWant);
    }

    public static void main(String[] args) {
        Printer<Integer> printer1 = new Printer<>(20);
        printer1.print();
        
        Printer<Double> printer2 = new Printer<>(23.6);
        printer2.print();
    }
}

输出结果:在这里插入图片描述

二.以下是泛型的一些使用场景

1.泛型在静态方法中的使用

public class Test2 {
    public static <T,V> void printer(T object1,V object2){
        System.out.println(object1);
        System.out.println(object2);
    }
    public static void main(String[] args) {
        Integer num = 6;
        String s = "你好啊";
        printer(num,s);
    }
}

2.泛型类的使用

class Pair<K, V> {
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

public class GenericClassExample {
    public static void main(String[] args) {
        Pair<String, Integer> pair = new Pair<>("apple", 5);
        System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue());
    }
}

3.泛型接口的使用

interface Stack<E> {
    void push(E item);
    E pop();
    boolean isEmpty();
}

class ArrayStack<E> implements Stack<E> {
    private Object[] elements;
    private int top;

    public ArrayStack() {
        elements = new Object[10];
        top = -1;
    }

    @Override
    public void push(E item) {
        if (top == elements.length - 1) {
            // 栈满时扩展数组
            Object[] newElements = new Object[elements.length * 2];
            System.arraycopy(elements, 0, newElements, 0, elements.length);
            elements = newElements;
        }
        elements[++top] = item;
    }

    @SuppressWarnings("unchecked")
    @Override
    public E pop() {
        if (isEmpty()) {
            return null;
        }
        return (E) elements[top--];
    }

    @Override
    public boolean isEmpty() {
        return top == -1;
    }
}

public class GenericInterfaceExample {
    public static void main(String[] args) {
        Stack<Integer> integerStack = new ArrayStack<>();
        integerStack.push(1);
        integerStack.push(2);
        integerStack.push(3);

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

4. 通配符相关

通配符(Wildcards)? 通配符来表示未知类型。

public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}

上界通配符(Upper Bounded Wildcards):使用<? extends T>表示类型参数的上界。

public void process(List<? extends Number> list) {
    // 只能读取,不能添加
}

下界通配符(Lower Bounded Wildcards):使用<? super T>表示类型参数的下界。

public void addNumbers(List<? super Integer> list) {
    list.add(new Integer(1));
}