Java基础 —— 泛型(一)

Java泛型

Java 泛型是一种在编写 Java 代码时用来提高类型安全性和重用性的机制。Java 泛型允许我们定义和使用一些通用的类、接口和方法,这些通用的类、接口和方法可以用于操作不同类型的数据。

下面是常见的Java 泛型的几种表现形式:

public class List<T> { ... }
public static <T> T[] toArray(T[] a) { ... }
public interface Map<K,V> { ... }

在上面的例子中,T、K、V 是类型参数,它们代表泛型类、泛型方法和泛型接口中的数据类型。使用泛型类、泛型方法和泛型接口时,我们可以传递实际的类型参数,例如:

List<String> list = new ArrayList<String>();
String[] array = toArray(list.toArray(new String[list.size()]));
Map<String,Integer> map = new HashMap<String,Integer>();

在这些例子中,我们可以看到使用泛型时传递了实际的类型参数。使用 Java 泛型可以使我们编写更加灵活的代码,提高代码的重用性和类型安全性,同时也可以提高程序的性能。

为什么引入泛型 - 泛型的目的和优势

泛型是在 Java 5中引入,Java 泛型的目的是让编程变得更加类型安全,减少代码中类型转换的错误,并增加代码的重用性。通过使用泛型,我们可以编写更加灵活的代码,而不必依赖于特定的数据类型。例如,如果我们要编写一个通用的容器类,可以使用泛型类,这样就可以避免使用 Object 类型,而不必担心类型转换错误的问题。

先看一个简单的应用:

public class Stack<T> {
    private T[] elements;
    private int size = 0;
    
    public Stack(int capacity) {
        elements = (T[]) new Object[capacity];
    }
    
    public void push(T element) {
        elements[size++] = element;
    }
    
    public T pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        T element = elements[--size];
        elements[size] = null;
        return element;
    }
    
    public boolean isEmpty() {
        return size == 0;
    }
}
Stack<Integer> intStack = new Stack<Integer>(10);
intStack.push(1);
intStack.push(2);
intStack.push(3);
System.out.println(intStack.pop()); // output: 3

如果在引入泛型以前上面的代码需要使用Object类,来看看它的实现:

public class Stack {
    private Object[] elements;
    private int size = 0;
    
    public Stack(int capacity) {
        elements = new Object[capacity];
    }
    
    public void push(Object element) {
        elements[size++] = element;
    }
    
    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object element = elements[--size];
        elements[size] = null;
        return element;
    }
    
    public boolean isEmpty() {
        return size == 0;
    }
}
Stack stack = new Stack(10);
stack.push(1);
stack.push(2);
stack.push(3);
int i = (Integer) stack.pop();
System.out.println(i); // output: 3

通过比较这两种实现方式,我们可以看到使用泛型可以使代码更加简洁和类型安全。在使用泛型的代码中,我们可以直接使用具体的数据类型,而不必进行类型转换,可以避免一些类型转换错误和运行时异常的问题。

再看看下一个例子:

List list = new ArrayList();
list.add("hello");
list.add(123);
String str = (String) list.get(1); // 运行时出错,因为 123 无法强制转换为字符串类型
//又或者你在使用list里面的数据前先做一个类型判断再使用
List<String> list = new ArrayList<>();
list.add("hello");
// list.add(123); 不能添加整数类型,因为 list 的类型参数为 String
String str = list.get(0); // 可以直接获取字符串类型,无需强制转换

前后对比显然第二段代码更简洁、明了和安全。

Java 泛型的优势包括:

  1. 类型安全性:Java 泛型可以让我们在编写代码时明确操作的数据类型,从而可以在编译时进行类型检查,避免类型转换错误和运行时异常。

  1. 代码重用性:使用泛型可以编写通用的类、接口和方法,可以在不同的应用程序中重复使用,提高代码的重用性。

  1. 程序可读性:泛型可以使代码更加清晰易读,因为我们可以在代码中直接使用具体的数据类型,而不是使用 Object 类型。

  1. 性能优化:泛型可以减少自动装箱和拆箱的操作,提高程序的性能。

Java 泛型的基本使用

先了解一个概念:类型参数。类型参数(type parameter)是指在泛型定义中所使用的占位符类型,它是一个未知的类型,用于代定某个具体类型。

Java 泛型不仅可以应用于类,还可以应用于方法和接口,分别称为泛型类、泛型方法和泛型接口。

泛型类

泛型类是具有一个或多个类型参数的类。在类定义中,类型参数使用尖括号(<>)括起来,可以用来表示类中的属性、方法的参数或返回值等。例如,下面的代码中的 T 和 E 就是类型参数:

public class Pair<T, E> {
    private T first;
    private E second;

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

    public T getFirst() {
        return first;
    }

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

    public E getSecond() {
        return second;
    }

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

在上面的代码中,Pair 类定义了两个类型参数 T 和 E,用于表示第一个和第二个元素的类型。这样,我们就可以创建不同类型的 Pair 对象,例如 Pair<String, Integer>、Pair<Integer, Double> 等。

泛型方法

泛型方法是在方法定义中使用类型参数的方法。在方法定义中,类型参数出现在方法名和参数列表之间的尖括号(<>)中,用于表示方法的参数类型、返回值类型或方法内部的局部变量类型。例如:

public class Utils {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}

在上面的代码中,我们定义了一个名为 printArray 的泛型方法,它接受一个类型参数为 T 的数组作为参数,用于打印数组中的所有元素。在方法定义中,我们使用了类型参数 T 来表示数组元素的类型,可以根据需要传入不同类型的数组。

泛型接口

泛型接口是具有一个或多个类型参数的接口。在接口定义中,类型参数使用尖括号(<>)括起来,可以用来表示接口中的方法的参数或返回值等。例如:

public interface List<T> {
    void add(T element);
    T get(int index);
}

在上面的代码中,我们定义了一个名为 List 的泛型接口,具有一个类型参数 T,用于表示列表中的元素类型。在 List 接口中,我们定义了两个方法 add 和 get,它们的参数和返回值都使用了类型参数。这样,我们就可以创建不同类型的列表实现,例如 ArrayList<String>、LinkedList<Integer> 等,它们都是 List 接口的实现类,但元素类型不同。


本文只是个人(EnergyNo8)学习笔记如有错误请网友指出。
如有引用或转载请标明出处!
努力、坚持,总会有收获!
______ EnergyNo8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

能量老8

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值