1 简介
泛型:参数类型,JDK5引入的新特性,在编译期检查参数类型(类型不匹配时,编译报错),运行时擦除类型(无类型概念,均统一处理)。
序号 | 应用范围 |
---|---|
1 | 类 |
2 | 接口 |
3 | 方法 |
2 Usage
2.1 泛型类
package com.monkey.java_study.datastructure.generic;
/**
* 泛型类.
*
* @author xindaqi
* @date 2021-12-16 11:38
*/
public class GenericClassTest<T> {
/**
* 数据
*/
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "GenericClassTest{" +
"data=" + data +
'}';
}
}
2.2 泛型接口
2.2.1 接口
package com.monkey.java_study.datastructure.generic;
/**
* 泛型接口.
*
* @author xindaqi
* @date 2021-12-16 12:04
*/
public interface IGenericInterfaceTest<T> {
/**
* 获取数据.
*
* @return 泛型类型的数据
*/
T getData();
}
2.2.2 String类型实现
package com.monkey.java_study.datastructure.generic.impl;
import com.monkey.java_study.datastructure.generic.IGenericInterfaceTest;
/**
* String类型接口实现.
*
* @author xindaqi
* @date 2021-12-16 12:08
*/
public class GenericInterfaceTestStringImpl implements IGenericInterfaceTest<String> {
@Override
public String getData() {
return "Generic interface implements!";
}
}
2.2.3 Integer类型实现
package com.monkey.java_study.datastructure.generic.impl;
import com.monkey.java_study.datastructure.generic.IGenericInterfaceTest;
/**
* Integer类型接口实现.
*
* @author xindaqi
* @date 2021-12-16 12:11
*/
public class GenericInterfaceTestIntegerImpl implements IGenericInterfaceTest<Integer> {
@Override
public Integer getData() {
return 1;
}
}
2.3 泛型方法
package com.monkey.java_study.datastructure.generic;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* 泛型方法.
*
* @author xindaqi
* @date 2021-12-16 11:57
*/
public class GenericMethodTest {
private static final Logger logger = LogManager.getLogger(GenericMethodTest.class);
/**
* 泛型方法.
*
* @param genericClassTest 泛型类
* @param <T> 泛型方法声明标识
* @return 泛型类型数据
*/
public <T> T genericMethod(GenericClassTest<T> genericClassTest) {
T data = genericClassTest.getData();
return data;
}
/**
* 泛型方法.
*
* @param data 泛型类型数据
* @param <T> 泛型方法声明标识
* @return 泛型类型数据
*/
public <T> T genericMethodDirect(T data) {
return data;
}
/**
* 设置泛型类型上限:extends.
*
* @param data 泛型类
* @param <T> 泛型方法声明标识
* @return 泛型类型数据
*/
public <T extends Number> T genericMethodWithTypeLimit(T data) {
return data;
}
/**
* 设置泛型类型上限:extends
*
* @param genericClassTest 泛型类
* @param <T> 泛型方法声明标识
* @return 泛型类型数据
*/
public <T> T genericMethodWithTypeLimit1(GenericClassTest<? extends Number> genericClassTest) {
T data = (T) genericClassTest.getData();
return data;
}
/**
* 无返回值的泛型方法.
*
* @param genericClassTest 泛型类
* @param <T> 泛型方法声明标识
*/
public <T> void genericMethodWithoutReturn(GenericClassTest<T> genericClassTest) {
T data = genericClassTest.getData();
logger.info(">>>>>>>>>泛型方法输出值:{}", data);
}
}
3 泛型擦除
Collection子类使用泛型,代码通过编译期检测后,
运行时使用不同的数据类型,
不会报错。
package com.monkey.java_study.datastructure.generic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* 伪泛型测试.
*
* @author xindaqi
* @date 2022-06-17 9:38
*/
public class PseudoGenericTest {
private static final Logger logger = LoggerFactory.getLogger(PseudoGenericTest.class);
public static void main(String[] args) {
// 伪泛型:泛型擦除
List<String> strList = new ArrayList(4);
strList.add("xioahua");
List intList = strList;
intList.add(1);
logger.info(">>>>>>>>>>List:{}", intList);
}
}
4 小结
(1)泛型:编译期检查类型,运行时忽略类型;
(2)泛型应用于类、接口和方法;
(3)类型安全,消除强制类型转换:泛型消除源码中的诸多强制类型转换,增加代码可读性;
(4)减少重复代码:提高代码利用率,使用泛型后,兼容不同类型数据的逻辑处理。
附件:完整测试样例
package com.monkey.java_study.functiontest;
import com.monkey.java_study.datastructure.generic.GenericClassTest;
import com.monkey.java_study.datastructure.generic.GenericMethodTest;
import com.monkey.java_study.datastructure.generic.impl.GenericInterfaceTestIntegerImpl;
import com.monkey.java_study.datastructure.generic.impl.GenericInterfaceTestStringImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
/**
* 泛型测试.
*
* @author xindaqi
* @date 2021-12-16 11:40
*/
public class GenericTest {
private static final Logger logger = LogManager.getLogger(GenericTest.class);
@Test
public void genericClassStringTest() {
GenericClassTest<String> genericClass = new GenericClassTest<>();
genericClass.setData("StringType");
logger.info(">>>>>>>>>>String:{}", genericClass);
}
@Test
public void genericClassIntegerTest() {
GenericClassTest<Integer> genericClass = new GenericClassTest<>();
genericClass.setData(1);
logger.info(">>>>>>>>>>Integer:{}", genericClass);
}
@Test
public void genericMethod1() {
GenericMethodTest genericMethodTest = new GenericMethodTest();
GenericClassTest<String> genericClassTest = new GenericClassTest<>();
genericClassTest.setData("Generic class 1.");
String data = genericMethodTest.genericMethod(genericClassTest);
logger.info(">>>>>>>>>>Data:{}", data);
}
@Test
public void genericMethod2() {
GenericMethodTest genericMethodTest = new GenericMethodTest();
String data = "Generic class 2";
String data1 = genericMethodTest.genericMethodDirect(data);
logger.info(">>>>>>>>>Data:{}", data1);
}
@Test
public void genericMethod3() {
GenericMethodTest genericMethodTest = new GenericMethodTest();
// String data = "Generic method 1";
Integer data = 1;
Integer data1 = genericMethodTest.genericMethodWithTypeLimit(data);
logger.info(">>>>>>>>>Data:{}", data1);
}
@Test
public void genericMethod4() {
GenericMethodTest genericMethodTest = new GenericMethodTest();
GenericClassTest<Double> genericClassTest = new GenericClassTest<>();
genericClassTest.setData(0.01);
Double data1 = genericMethodTest.genericMethodWithTypeLimit1(genericClassTest);
logger.info(">>>>>>>>>Data:{}", data1);
}
@Test
public void genericMethod5() {
GenericMethodTest genericMethodTest = new GenericMethodTest();
GenericClassTest<String> genericClassTest = new GenericClassTest<>();
genericClassTest.setData("Generic class 3");
genericMethodTest.genericMethodWithoutReturn(genericClassTest);
}
@Test
public void genericInterface1() {
GenericInterfaceTestStringImpl genericInterfaceTest = new GenericInterfaceTestStringImpl();
String data = genericInterfaceTest.getData();
logger.info(">>>>>>>>>>Data:{}", data);
}
@Test
public void genericInterface2() {
GenericInterfaceTestIntegerImpl genericInterfaceTest = new GenericInterfaceTestIntegerImpl();
Integer data = genericInterfaceTest.getData();
logger.info(">>>>>>>>>>Data:{}", data);
}
}