Java基础知识之泛型简单介绍

举报
yd_273762914 发表于 2021/08/10 23:22:08 2021/08/10
【摘要】 1、什么是java泛型? java泛型:英文名称是generics,泛型是jdk5引入的一个新特性,java泛型的本质就是参数化类型,就是所有的操作数据类型被指定为一个参数。对参数化类型进行操作的实体(例如类、接口或方法)称为泛型实体。 2、java泛型类 泛型类:必须先声明,再使用;声明是通过<T,E, ...>实现的;约定泛型可以使用单个大写...

1、什么是java泛型?

java泛型:英文名称是generics,泛型是jdk5引入的一个新特性,java泛型的本质就是参数化类型,就是所有的操作数据类型被指定为一个参数。对参数化类型进行操作的实体(例如类、接口或方法)称为泛型实体。

2、java泛型类

泛型类:必须先声明,再使用;声明是通过<T,E, ...>实现的;约定泛型可以使用单个大写字母T、E、K、V等表示


import java.lang.reflect.Field;

public class GenericsSimpleExample { public static void main(String[] args) { A<String , Integer> a0 = new A<>(); a0.t= "testStr"; A<Integer , Integer> a1 = new A<>(); a1.t = 100; //  泛型参数在使用时要引用数据类型,不能是基本数据类型,比如int等等 //A<Integer , int> a2 = new A<>(); // 泛型类如果不指定具体的参数类型,默认数据类型是object Class<A> cls = A.class; Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } // 泛型类在具体实现上可以看出不同数据类型,实践上是相同的数据类型,可以通过hashcode进行验证 System.out.println(a0.getClass().hashCode()); System.out.println(a1.getClass().hashCode()); } static class A <T , E> { public T t; public void test0(T  t) { } }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

注意要点:

  • 泛型类的参数类型不能是基本数据类型,要使用引用数据类型
  • 泛型类在不指定具体数据类型时候,默认是使用object类型的
  • 泛型类具体使用上可以使用不同的数据类型,实践上是相同的数据类型

3、从泛型类派生子类

  • 1、子类是泛型的情况,子类要和父类的泛型类型一致
class A<T> extends B<T>{}

  
 
  • 1
  • 2、子类不是泛型的情况,父类要明确泛型的数据类型
class A extends  B<String>{}

  
 
  • 1

4、泛型接口

泛型接口语法:

interface 接口名称 <泛型标识,泛型标识, ...>{
  泛型标识 方法名();
  ...
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 1、实现类也是泛型类,泛型类型要和接口一致
interface B <T,V> {}
class A<T,V> implements B<T,V>{}

  
 
  • 1
  • 2
  • 2、实现类不是泛型类,接口要指定具体的类型
class B implements B<String,Integer>{}

  
 
  • 1

5、泛型方法

泛型方法语法:

修饰符 <T,E,...> 返回值类型 方法名 (形参列表){
  方法体;
}

  
 
  • 1
  • 2
  • 3

泛型方法特征:

  • 只有声明了<T>的方法才是泛型方法,仅仅传参使用了泛型的,不是泛型方法
  • 和泛型类一样,也可以使用K、V、T、E等等参数表示泛型

public class GenericsMethodExample { public static void main(String[] args) { A0 a0 = new A0(); a0.test0("hello"); A1<Integer> a1 = new A1<>(); a1.test("hi", "hello"); A1.test1("hello world"); } static class A0 { public <T, E> T test0(T t) { System.out.println("t = " + t); return null; } } static class A1<K> { /** * 泛型方法的类型和泛型类一致时,以具体方法的为准 * @param k * @param t */ public <T, K> T test(T t , K k) { System.out.println("t = " + t); System.out.println("k = " + k); return null; } /** * static方法要使用泛型,必须指定为泛型方法加上{@code <K>} * @param k */ public static <K> void test1(K k) { } }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

归纳:

  • 泛型方法的类型和泛型类一致时,以具体方法的为准
  • static方法要使用泛型,必须指定为泛型方法加上

6、泛型通配符

类型通配符一般是使用?代替具体的类型实参,所以类型通配符是类型实参,而不是类型形参

public class GenericsWildcardExample { public static void main(String[] args) { A<String> a0 = new A<>(); show(a0); A<Integer> a1 = new A<>(); show(a1); } public static void show(A<?> a){ System.out.println(a.getClass()); } static class A<T> { }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

7、类型通配符上限

语法:

/接口 <? extends 实参类型>

  
 
  • 1

要求改泛型类型只能是实参类型或者实参的子类类型


  public class GenericsWildcardExample { public static void main(String[] args) { A<A1> a11 = new A<>(); A<A2> a12 = new A<>(); A<A3> a13 = new A<>(); // 只能使用A2及其子类 show0(a12); show0(a13); } public static void show0(A<? extends A2> a) {} static class A<T> { } static class A1{} static class A2 extends A1{} static class A3 extends A2{}
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

8、类型通配符下限

语法:

/接口 <? super 实参类型>

  
 
  • 1

要求改泛型类型只能是实参类型或者实参的父类类型

public class GenericsWildcardExample { public static void main(String[] args) { A<A1> a11 = new A<>(); A<A2> a12 = new A<>(); A<A3> a13 = new A<>(); // 只能使用A2及其父类 show1(a11); show1(a12); } public static void show1(A<? super A2> a){} static class A<T> { } static class A1{} static class A2 extends A1{} static class A3 extends A2{}
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

9、什么是泛型擦除?

泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型有关的信息会被擦除
掉,我们称之为 类型擦除

9.1、无限制类型擦除

在这里插入图片描述


import java.lang.reflect.Field;


public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls0 = A.class; Field[] fields = cls0.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } } static class A <T>{ T t; }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

打印:

t:Object

9.2、有限制类型擦除

在这里插入图片描述


import java.lang.reflect.Field;


public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls1 = A1.class; Field[] fields1 = cls1.getDeclaredFields(); for (Field field : fields1) { System.out.println(field.getName() + ":" + field.getType().getSimpleName()); } } static  class A1<T extends Number> { T t; }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

打印:

t:Number

9.3、方法类型擦除

在这里插入图片描述


import java.lang.reflect.Method;

public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls2 = A2.class; Method[] methods = cls2.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName()); } } static class A2<T extends Number> { T t; public <K extends Number> K test(K k) { return null; } }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

打印

test:Number

9.4、桥接方法

在这里插入图片描述

interface MyInter<T>{
  T fun1();
}
class DD implements MyInter<String>{
  @Override
  public String fun1() { return null;
 }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

import java.lang.reflect.Method;


public class GenericsWipeExample { public static void main(String[] args) { Class<?> cls3 = A3.class; Method[] methodss = cls3.getDeclaredMethods(); for (Method method : methodss) { System.out.println(method.getName() + ":" + method.getReturnType().getSimpleName()); } } interface MyInter<T>{ T test(); } class A3 implements MyInter<String> { @Override public String test() { return null; } }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

打印:

test:String
test:Object

10、泛型和反射

 Class<?> cls0 = A.class;
Field[] fields = cls0.getDeclaredFields();
for (Field field : fields) { System.out.println(field.getName() + ":" + field.getType().getSimpleName());
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

文章来源: smilenicky.blog.csdn.net,作者:smileNicky,版权归原作者所有,如需转载,请联系作者。

原文链接:smilenicky.blog.csdn.net/article/details/119549581

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。