- 👑专栏内容:Java
- ?个人主页:子夜的星的主页
- 💕座右铭:前路未远,步履不停
在传统的编程方法中,类和方法通常被限定为使用特定的类型。这些类型可能是基础的数据类型(如整数、字符等),或者是由程序员自己定义的复杂类型。这种方式在处理单一类型数据时很有效,但当我们需要编写更加灵活、能够适用于多种数据类型的代码时,这种严格的类型限制就变成了一个约束。
泛型,就是为了解决这种限制而生的。简单来说,泛型可以理解为一种“类型模板”,它允许程序员编写的代码能够适应不同的数据类型,而不必为每种可能的数据类型都编写一个新版本。
泛型的厉害之处,就在于它的灵活性和重用性。你可以写一个泛型方法或类,然后在需要的时候用具体的类型去实例化它,比如整数、字符串或者是你自定义的任何类型。这样,你就可以用同一套代码处理不同类型的数据,极大地提高了代码的通用性和可维护性。
泛型的基本语法主要包括以下几个方面:
泛型类和接口:
<T>
来声明一个泛型类或接口。T
是类型参数,代表一种未指定的类型。在实例化类或接口时,你可以用具体的类型替换它。public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
这个例子中,Box
类可以用任何类型的对象来实例化,例如Box<Integer>
或Box<String>
。
泛型方法:
<T>
来声明一个泛型方法。public <T> T genericMethod(T t) {
return t;
}
这个方法可以接受任何类型的参数,并返回相同类型的对象。
类型通配符:
?
表示未知类型,通常用在参数、字段、局部变量上,以及泛型方法的返回类型上。public void processElements(List<?> elements) {
for (Object e : elements) {
// 处理e
}
}
List<?>
可以接受任何类型的List
。
限定的类型参数:
extends
关键字来限定类型参数的上界(即它必须是特定类或接口的子类型)。public <T extends Number> double sum(List<T> numbers) {
double sum = 0.0;
for (Number n : numbers) {
sum += n.doubleValue();
}
return sum;
}
这个方法只接受Number
类型或其子类的List
。
泛型存在的意义:
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
MyArray<Integer> list = new MyArray<Integer>();
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!
在编译时,Java编译器将所有的泛型类型参数替换掉,这个过程就是类型擦除。
Object
。<T extends Number>
),编译器将类型参数替换为它的第一个边界。<T>
),编译器将类型参数替换为Object
。Java的泛型机制是在编译级别实现的,编译器生成的字节码在运行期间并不包含泛型的类型信息。
class MyArray<T> {
public T[] array = (T[])new Object[10];
public T getPos(int pos) {
return this.array[pos];
}
public void setVal(int pos,T val) {
this.array[pos] = val;
}
public T[] getArray() {
return array;
}
}
public class demo1 {
public static void main(String[] args) {
MyArray<Integer> myArray1 = new MyArray<>();
Integer[] strings = myArray1.getArray();
}
}
由于类型擦除的原因,不能直接创建一个泛型数组。类型擦除会将泛型类型参数T
替换为Object
,这导致了类型不匹配,从而在运行时抛出ClassCastException
。
语法:方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }
例子:写一个泛型方法,用于交换数组中两个元素的位置:
public class GenericMethodTest {
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray ) {
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("整型数组元素为:");
printArray(intArray); // 传递一个整型数组
System.out.println("\n双精度型数组元素为:");
printArray(doubleArray); // 传递一个双精度型数组
System.out.println("\n字符型数组元素为:");
printArray(charArray); // 传递一个字符型数组
}
}
<T>
。