一、什么是泛型,为什么引入泛型
我们在完成一个工具类的编写后,如果这个工具类只适用于一种数据类型,那么功能代码的复用程度不够。如果需要更换数据类型,只能重新完成对应数据类型的功能代码。有可能出现各式各样的类型,工作是重复的,既耽误时间又消耗精力。
Java的泛型就是来解决这样的问题,它可以实现同一套代码适用于各种数据类型,大大提高了代码的复用性。
二、java中泛型的应用
泛型的应用分为三种:
1、方法中的泛型
public static <T> 返回值类型 方法名 (必须存在一个对应泛型的参数) {
方法体内可以使用自定义泛型
}
使用注意事项:
- 自定义泛型声明在返回值之前,已保证方法的参数和返回值都可以使用对应的泛型
- 方法声明的泛型,在方法的参数中必须有一个参数是对应声明的自定义泛型。当前参数是用于约束方法内所有使用到泛型的位置对应的具体数据类型是什么。
import java.util.Arrays;
public class Demo1 {
public static void main(String[] args) {
Integer test = test(123);
String test2 = test("你好");
Demo1 test3 = test(new Demo1());
String[] arr1 = { "烤羊排", "土豆牛肉", "黄焖鸡米饭", "烤羊肉串", "烤韭菜", "烤蒜" };
printArray(arr1);
Integer[] arr2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
printArray(arr2);
}
public static <T> T test(T t) {
return t;
}
/**
* 展示任意类型数组的方式
* @param <T> 自定义泛型无意义占位符
* @param arr 用户指定类型的数组,同时约束自定义泛型对应的具体数据类型
*/
public static <T> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
2、类中的泛型
class 类名 <自定义泛型无意义大写字母占位符> {
在类内的成员变量和成员方法都可以使用自定义泛型
建议: 成员变量不建议使用自定义泛型
}
使用注意事项:
-
类声明自定义泛型,需要通过创建对象的方式来约束
TypeA<String> typeA = new TypeA<String>(); Eclipse标准写法
TypeA<String> typeA = new TypeA<>(); IDEA写法
-
类声明泛型约束之后,在类内的所有成员方法中使用的泛型都是类约束的泛型具体数据类型。
-
如果没有约束类声明泛型,所有使用到泛型的位置都是Object,但是这种使用方法并不推荐。
-
类声明的自定义泛型不能用于类内的静态方法,因为没有对象的创建。
3、接口中的泛型
interface 接口名 <自定义泛型无意义占位符> {
接口中的泛型有且只能用于成员方法
}
使用注意事项:
- 接口声明的泛型,有且只能用于类内的成员方法。
- 遵从带有自定义泛型的接口的类,一种可以遵从过程中明确告知泛型具体类型,一种是在创建类对象是明确泛型具体数据类型。
class TypeA<T> implements A<String>
正确
接口的泛型明确接口中的方法,使用泛型对应的具体数据类型
类声明的泛型用于自定义约束自己类内的方法class TypeA<E> implements A<T>
错误
接口中的泛型没有明确数据类型,也无法通过类创建对象的过程中明确
泛型对应的具体数据类型,无法编译