泛型的使用
前言
Github:https://github.com/HealerJean
1、泛型标识
E - Element
(在集合中使用,因为集合中存放的是元素) 以下都是表示泛型名称。换成其他字母都没关系
标识 | 代表 | 说明 |
---|---|---|
T | Type | Java 类,T 的使用,可以直接当做方法使用哦,函数里面可以对T进行操作 |
? | Type | 表示不确定的java类型 |
K | Key | 键 |
V | Value | 值 |
N | Number | 数值类型 |
1.1、泛型中<?>
和<T>
有什么区别
<T>
:的使用,可以直接当做方法使用哦,函数里面可以对T进行操作
<?>
:表示不确定的java类型
/**
* T 的使用,可以直接当做方法使用哦,函数里面可以对T进行操作
*/
public static <T> void printT(ArrayList<T> al){
Iterator<T> it = al.iterator();
while(it.hasNext())
{
T it1 = it.next();
System.out.println(it1.toString());
}
}
/**
* ? 的使用
*/
public static void printColl(ArrayList<?> al){
Iterator<?> it = al.iterator();
while(it.hasNext())
{
System.out.println(it.next().toString());
}
}
2、泛型的使用以及存在时期
2.1、泛型的简单使用List
、ArrayList
//1、可以打印
List list = new ArrayList();
list.add(1);
list.add("String");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());//正常打印
}
2.2、泛型存在于编译时期
Java
中编译后的class
不会包含泛型信息,泛型只在编译阶段有效,成功编译过后的class
文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段
private static void testEquals() {
ArrayList<String> a = new ArrayList<String>();
ArrayList b = new ArrayList();
Class c1 = a.getClass();
Class c2 = b.getClass();
System.out.println(c1 == c2); //true 表示已经经过编译了,没有任何泛型信息
System.out.println(a == b); //false
}
2.3、利用反射调用arrylist
private static void invokeMethod() {
ArrayList<String> a = new ArrayList<String>();
Class c = a.getClass();
a.add("CSDN_SEU_Cavin");
try{
Method method = c.getMethod("add",Object.class);
method.invoke(a,100);
System.out.println(a); //[CSDN_SEU_Cavin, 100]
}catch(Exception e){
e.printStackTrace();
}
}
3、自建反射对象的使用
3.1、具有泛型,T
public static class FX<T> {
private T ob; // 定义泛型成员变量
public FX(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
public static void main(String[] args) {
FX<Integer> intOb = new FX(100);
intOb.showTyep();
System.out.println("value = " + intOb.getOb());
System.out.println("----------------------------------");
FX<String> strOb = new FX("CSDN_SEU_Calvin");
strOb.showTyep();
System.out.println("value = " + strOb.getOb());
}
T : java.lang.Integer
value = 100
----------------------------------
T : java.lang.String
value = CSDN_SEU_Calvin
3.2
、new
的实现,没有泛型
public static class FX {
private Object ob; // 定义泛型成员变量
public FX(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void showTyep() {
System.out.println("T的实际类型是: " + ob.getClass().getName());
}
}
object =: java.lang.Integer
value = 100
----------------------------------
object =: java.lang.String
value = CSDN_SEU_Calvin
public static void main(String[] args) {
FX intOb = new FX(new Integer(100));
intOb.showTyep();
System.out.println("value= " + intOb.getOb());
System.out.println("----------------------------------");
FX strOb = new FX("CSDN_SEU_Calvin");
strOb.showTyep();
System.out.println("value= " + strOb.getOb());
}
4、注意事项:
4.1、确定的泛型类型,传参必须确定类型才能成功
public class ThreeMain {
public static void main(String[] args) {
FX<Number> ex_num = new FX<Number>(100);
getData(ex_num);
FX<Integer> ex_int = new FX<Integer>(200);
// getData(ex_int);//编译错误
}
//此行若把Number换为“?”或者“T” getData(ex_int);编译通过
public static void getData(FX<Number> temp) {
//do something...
}
public static class FX<T> {
private T ob;
public FX(T ob) {
this.ob = ob;
}
}
}
4.2、<? extends Number>
和<? supers Number>
<? extends Number>
:表示继承Number
的都能够使用
<? supers Number>
:表示父类以上都能够使用
public class ThreeMain {
public static void main(String[] args) {
FX<Number> ex_num = new FX<Number>(100);
getUpperNumberData(ex_num);
FX<Integer> ex_int = new FX<Integer>(200);
getUpperNumberData(ex_int);
}
public static void getUpperNumberData(FX<? extends Number> temp){
System.out.println("class type :" + temp.getClass());
}
public static class FX<T> {
private T ob;
public FX(T ob) {
this.ob = ob;
}
}
4.3、不能对确切的泛型类型使用instanceof
操作
public class FourMain {
public static void main(String[] args) {
FX<Number> ex_num = new FX<Number>(100);
FX<Integer> ex_int = new FX<Integer>(200);
// 报错,不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。不确定的应该使用 ?
if(ex_num instanceof FX<Number>){
}
if(ex_num instanceof FX<?>){ //使用T也是错误的,以为T也是已知的java类型
}
}
public static class FX<T> {
private T ob;
public FX(T ob) {
this.ob = ob;
}
}
}
5、泛型的使用
5.1、DTO
@Data
@Accessors(chain = true)
public class Bean03DTO<A, N> {
private A age;
private N name;
}
@Data
@Accessors(chain = true)
public class Bean03OtherDTO<F> {
private F friend;
}
public class Bean31ParentDTO<P> {
private P parent;
}
@Data
public class Bean31SonDTO<S extends Bean31ParentDTO>{
private S son;
}
5.2、泛型使用
public class GenericService {
/**
* 1、有多少泛型,前面放多少个
*/
public static <A, N> A invokeOne(Bean03DTO<A, N> bean03DTO) {
return bean03DTO.getAge();
}
/**
* 2、有多少泛型,前面放多少个
*/
public static <A, N, F> Pair<Bean03DTO<A, N>, Bean03OtherDTO<F>> invokeTwo(Bean03DTO<A, N> dto,
Bean03OtherDTO<F> other) {
Pair<Bean03DTO<A, N>, Bean03OtherDTO<F>> pair = new Pair<>(dto, other);
return pair;
}
/**
* 3、继承中的泛型引用
*/
public static <S extends Bean31ParentDTO<String>> S invokeThree(Bean31SonDTO<S> bean31SonDTO){
return bean31SonDTO.getSon();
}
/**
* 3、继承中的泛型引用,前面放多少个
*/
public static <S extends Bean31ParentDTO<String>, A, N> S invokeThree(Bean31SonDTO<S> bean31SonDTO,
Bean03DTO<A, N> bean03DTO){
return bean31SonDTO.getSon();
}
}
@Slf4j
public class TestMain {
@Test
public void test(){
Bean03DTO<Integer, String> bean03DTO = new Bean03DTO<>();
bean03DTO.setAge(11);
bean03DTO.setName("HealerJean");
log.info("invoke:{}", GenericService.invokeOne(bean03DTO));
Bean03OtherDTO<String> bean03OtherDTO = new Bean03OtherDTO();
bean03OtherDTO.setFriend("friend");
log.info("invoke:{}", GenericService.invokeTwo(bean03DTO,bean03OtherDTO));
}
}