java泛型
java泛型的实现采取了“伪泛型”的策略,即在语法上支持泛型,但是在代码编译阶段会进行“类型擦除”,将所有的泛型表示(尖括号中的内容)都替换成具体的类型(原生类型)。
泛型的意义
适用于多种数据类型执行相同的代码(代码的复用)
简单示例:不同类型的两个数相加
public static void main(String[] args) {
int a1 = 3, b1 = 4;
float a2 = 3, b2 = 4;
double a3 = 3.1, b3 = 4.1;
System.out.println(add(a1, b1));
System.out.println(add(a2, b2));
System.out.println(add(a3, b3));
}
private static int add(int a, int b) {
return a + b;
}
private static float add(float a, float b) {
return a + b;
}
private static double add(double a, double b) {
return a + b;
}
使用泛型
public static void main(String[] args) {
int a1 = 3, b1 = 4;
float a2 = 3, b2 = 4;
double a3 = 3.1, b3 = 4.1;
System.out.println(add(a1, b1));
System.out.println(add(a2, b2));
System.out.println(add(a3, b3));
}
private static <T extends Number> Double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
泛型类的使用
简单示例
class Point<T> { // T是type的简称,类型由外部传入决定
private T var;
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
public class demo {
public static void main(String args[]) {
Point<String> p = new Point<String>(); // 将var类型设置为String类型
p.setVar("hello");
System.out.println(p.getVar().length());
}
}
将泛型类用在前端请求的返回值上,如:
/**
* @Description 前端统一返回类
**/
public class Result<D>
{
/**
* 0 为成功,1为失败
*/
public static final String SUCCESS = "0";
public static final String FAIL = "1";
private String code;
private D data;
private String msg;
// getter setter
}
这样可以在返回给前端的时候,放进data里面的返回数据可以是任意类型的,比如String,Object,int等等。
泛型接口的使用
简单示例
定义一个泛型接口
public interface GenericInterface<T> {
void doSomething(T item);
}
创建一个实现这个泛型接口的类
public class GenericClass implements GenericInterface<String> {
@Override
public void doSomething(String item) {
System.out.println("Doing something with " + item);
}
}
使用这个类
public class Main {
public static void main(String[] args) {
GenericInterface<String> obj = new GenericClass();
obj.doSomething("Hello, World!");
}
}
泛型方法的使用
为什么要使用泛型方法,不使用泛型类呢?
因为泛型类要在实例化的时候就指明类型,如果想换一种类型,就需要重新new一次,而泛型方法可以在调用的时候指明类型,更加灵活。
简单示例
public class GenericMethodExample {
// 泛型方法,接受一个类型为T的数组并返回其长度
public static <T> int getArrayLength(T[] array) {
return array.length;
}
public static void main(String[] args) {
// 使用泛型方法获取整数数组的长度
int[] intArray = {1, 2, 3, 4, 5};
int lengthOfIntArray = getArrayLength(intArray);
System.out.println("Length of int array: " + lengthOfIntArray);
// 使用泛型方法获取字符串数组的长度
String[] stringArray = {"Hello", "World"};
int lengthOfStringArray = getArrayLength(stringArray);
System.out.println("Length of string array: " + lengthOfStringArray);
}
}
这样就不用new两个GenericMethodExample类对象了,只需要创建一个对象,然后调用两次不同类型传参的方法。
特别适用于工具类和方法,这些工具类和方法需要处理不同类型的参数,但在逻辑上是通用的。
泛型的上限与下限
即,在使用泛型的时候,可以限制传入泛型类型实参上下边界(类型实参只准传入某种类型的父类或某种类型的子类)
上限
上限意味着泛型类型参数必须是某个特定类型或子类。使用extends关键字来定义上限。
class Info<T extends Number> { // 此处泛型只能是数字类型
private T var;
public void setVar(T var) {
this.var = var;
}
public T getVar() {
return this.var;
}
public String toString() {
return this.var.toString();
}
}
public class demo {
public static void main(String args[]) {
Info<Integer> i = new Info<Integer>();
}
}
下限
下限意味着泛型类型参数必须是某个特定类型或其超类。使用super关键字来定义下限。
class Info<T> {
private T var;
public void setVar(T var) {
this.var = var;
}
public T getVar() {
return this.var;
}
public String toString() {
return this.var.toString();
}
}
public class demo {
public static void main(String args[]) {
Info<String> i = new Info<String>();
Info<Object> i = new Info<Object>();
i1.setVar("hello");
i2.setVar(new Object());
fun(i);
fun(i);
}
public static void fun(Info<? super String> temp) { // 只能接收String或Object类型的泛型,String类的父类只有Object类
System.out.print(temp + ", ");
}
}