2022.4.25 集合 泛型(Generic)

泛型

概念:

Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。泛型的本质就是参数化类型(将类型参数化),也就是所操作的数据类型被指定为一个参数。

类型:

  • E - Element (在集合中使用,因为集合中存放的是元素)

  • T - Type(表示Java 类,包括基本的类和我们自定义的类)

  • K - Key(表示键,比如Map中的key)

  • V - Value(表示值)

  • N - Number(表示数值类型)

  • ? - (表示不确定的java类型)

  • S、U、V - 2nd、3rd、4th types

泛型类

泛型类定义语法

1 class 类名称 <泛型标识,泛型标识...>{//可以作为成员变量、方法参数、方法返回值的类型
2     private 泛型标识 变量名;
3     ......
4 }

Generic

复制代码
 1 package com.xing.generic;
 2  3 /*
 4     泛型类的定义
 5     泛型标识相当于类型参数
 6     T 在创建Generic类的对象时,需指定具体的参数类型
 7  */
 8 public class Generic<T> {
 9     private T key;
10     // 泛型  不能实例化   T t = new T();  因为不知T的具体类型
11 12     public Generic() {
13     }
14 15     public Generic(T key) {
16         this.key = key;
17     }
18 19     public T getKey() {
20         return key;
21     }
22 23     public void setKey(T key) {
24         this.key = key;
25     }
26 27     @Override
28     public String toString() {
29         return "Generic{" +
30                 "key=" + key +
31                 '}';
32     }
33 }
复制代码

泛型类的使用

泛型类,是在实例化类的时候指明泛型的具体类型。

类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();

注:Java1.7以后,后面的<>中的具体的数据类型可以省略不写

类名<具体的数据类型> 对象名 = new 类名<>(); 称为菱形语法

泛型类注意事项

  • 泛型类在创建对象的时候,如果没有指定具体的数据类型,此时,操作类型是Object

  • 泛型的类型参数只能是类类型,不能是基本数据类型(int等)

  • 泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型

  • 泛型类中不能定义静态方法,除非是泛型方法(如果static方法要使用泛型能力,就必须使其成为泛型方法)

Generic

复制代码
 1 package com.xing.generic;
 2  3 /*
 4     泛型类的定义
 5     泛型标识相当于类型参数
 6     T 在创建Generic类的对象时,需指定具体的参数类型
 7  */
 8 public class Generic<T> {
 9     private T key;
10 11     public Generic() {
12     }
13 14     public Generic(T key) {
15         this.key = key;
16     }
17 18     public T getKey() {
19         return key;
20     }
21 22     // 报错  泛型类中不能定义静态方法,除非是泛型方法
23     // public static T get1() {
24     //     return "报错";
25     // }
26 27     //如果static方法要使用泛型能力,就必须使其成为泛型方法
28     //不会受泛型类的泛型标识影响   泛型方法的泛型标识与泛型类的泛型标识无关  
29     //<T,E,V> 说明这个方法是范型方法而已    返回值与参数的泛型标识必须在泛型列表<T,E,V>中
30     public static <T,E,V> T get(T t) {
31         return t;
32     }
33 34     public void setKey(T key) {
35         this.key = key;
36     }
37 38     @Override
39     public String toString() {
40         return "Generic{" +
41                 "key=" + key +
42                 '}';
43     }
44 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7         //泛型类在创建对象的时候来指定操作的具体数据类型 必须是引用类型
 8  9         // 使用的空参构造
10         Generic<String> stringGeneric = new Generic<>();
11 12         // 使用的带参构造   我们指定泛型为String类型,所以参数只能是String类型
13         Generic<String> stringGeneric1 = new Generic<>("小明");
14         String key = stringGeneric1.getKey();
15         System.out.println(key);//小明
16 17         // 使用的带参构造   我们指定泛型为Integer类型,所以参数只能是Integer类型
18         Generic<Integer> integerGeneric = new Generic<>(100);
19         Integer key1 = integerGeneric.getKey();
20         System.out.println(key1);//100
21 22 23         // 泛型类在创建对象的时候,如果没有指定具体的数据类型,此时,操作类型是Object
24         Generic generic = new Generic("abc");
25         Object key2 = generic.getKey();
26         System.out.println(key2);//abc
27 28 29         // 泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
30         System.out.println(stringGeneric.getClass());//class com.xing.generic.Generic
31         System.out.println(integerGeneric.getClass());//class com.xing.generic.Generic
32         //可以结合后面的泛型擦除理解,泛型擦除之后 Generic < String > 和Generic< Integer >都是Generic类
33         System.out.println(stringGeneric.getClass()==integerGeneric.getClass());//true
34 35     }
36 37 }
复制代码

测试

Box

复制代码
 1 package com.xing.generic;
 2  3 import java.util.ArrayList;
 4 import java.util.Random;
 5 //泛型可以写多个   泛型列表
 6 public class Box<T,E> {
 7  8     Random random = new Random();
 9 10     // 存放物品
11     ArrayList<T> arrayList = new ArrayList<>();
12     ArrayList<E> list = new ArrayList<>();
13 14     // 向集合中添加物品
15     public void put(T t) {
16         arrayList.add(t);
17     }
18 19     // 随机拿取集合中的物品
20     public T get() {
21         // nextInt()方法的参数是一个限定范围,随机数的范围不超过arrayList.size()
22         T t = arrayList.get(random.nextInt(arrayList.size()));
23         return t;
24     }
25 26     public void put1(E e) {
27         list.add(e);
28     }
29 30     // 随机拿取集合中的物品
31     public E get1() {
32         // nextInt()方法的参数是一个限定范围,随机数的范围不超过arrayList.size()
33         E e = list.get(random.nextInt(list.size()));
34         return e;
35     }
36 37     public void print(T t, E e) {
38 39         System.out.println(t.toString()+e.toString());
40     }
41 42 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7  8         Box<String, Integer> stringIntegerBox = new Box<>();
 9 10         String[] goods = {"手机","耳机","洗衣液"};
11         for (String good : goods) {
12             stringIntegerBox.put(good);
13         }
14         System.out.println(stringIntegerBox.get());
15 16         Integer[] money = {100, 1000, 50};
17         for (Integer integer : money) {
18             stringIntegerBox.put1(integer);
19         }
20         System.out.println(stringIntegerBox.get1());
21 22 23         stringIntegerBox.print("小明多大了?   ",20);//小明多大了?   20
24 25     }
26 27 }
复制代码

从泛型类派生子类

子类也是泛型类,子类和父类的泛型类型要一致

Parent

复制代码
 1 package com.xing.generic;
 2  3 // 父类
 4 public class Parent<E> {
 5     private E value;
 6     public E getValue() {
 7         return value;
 8     }
 9     public void setValue(E value) {
10         this.value = value;
11     }
12 }
复制代码

ChildFirst

复制代码
1 package com.xing.generic;
2 3 // 泛型类派生子类,子类也是泛型类,那么子类的泛型标识要含有父类的泛型标识。
4 public class ChildFirst<T,V> extends Parent<T> {
5     @Override
6     public T getValue() {
7         return super.getValue();
8     }
9 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7  8         //创建子类对象时 会先去创建父类对象  将子类泛型标识传递给父类  父类的泛型类型就会定义为其类型
 9         ChildFirst<String, Integer> stringIntegerChildFirst = new ChildFirst<>();
10 11         stringIntegerChildFirst.setValue("abc");
12         System.out.println(stringIntegerChildFirst.getValue());//abc
13 14     }
15 16 }
复制代码

子类不是泛型类,父类要明确泛型的数据类型

Parent

复制代码
 1 package com.xing.generic;
 2  3 // 父类
 4 public class Parent<E> {
 5     private E value;
 6     public E getValue() {
 7         return value;
 8     }
 9     public void setValue(E value) {
10         this.value = value;
11     }
12 }
复制代码

ChildFirst 就相当于一个普通的类了

复制代码
 1 package com.xing.generic;
 2  3 // 泛型类派生子类,如果子类不是泛型类,那么父类要明确数据类型
 4 public class ChildFirst extends Parent<Integer> {
 5     @Override
 6     public Integer getValue() {
 7         return super.getValue();
 8     }
 9     @Override
10     public void setValue(Integer value) {
11         super.setValue(value);
12     }
13 }
复制代码

泛型接口

泛型接口的定义语法

1 //泛型接口  不能创建范型静态常量   常量在创建时必须初始化  定义范型时只能是定义
2 //接口可以包含抽象方法  静态常量
3 interface 接口名称 <泛型标识,泛型标识,…> {
4     //默认 public static final
5     String name = "张三";
6     泛型标识 方法名(); 
7     .....
8 }

泛型接口的使用

实现类也是泛型类,实现类和接口的泛型类型要一致

Generator

1 package com.xing.generic;
2 3 //泛型接口  不能创建范型静态常量   常量在创建时必须初始化  定义范型时只能是定义
4 //接口可以包含抽象方法  静态常量
5 public interface Generator<T> {
6     T getKey();
7 }

Pair

复制代码
 1 package com.xing.generic;
 2  3 /**
 4  * 泛型接口的实现类,是一个泛型类,
 5  * 那么要保证实现接口的泛型类泛型标识包含泛型接口的泛型标识
 6  * @param <T>
 7  * @param <E>
 8  */
 9 public class Pair<T,E> implements Generator<T> {
10 11     private T key;
12     private E value;
13 14     public Pair(T key, E value) {
15         this.key = key;
16         this.value = value;
17     }
18 19     @Override
20     public T getKey() {
21         return key;
22     }
23 24     public E getValue() {
25         return value;
26     }
27 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7         Pair<String, Integer> stringIntegerPair = new Pair<String, Integer>("小明",100);
 8  9         String key = stringIntegerPair.getKey();
10         System.out.println(key);//小明
11         Integer value = stringIntegerPair.getValue();
12         System.out.println(value);//100
13 14     }
15 16 }
复制代码

实现类不是泛型类,接口要明确数据类型

Generator

1 package com.xing.generic;
2 3 4 //泛型接口
5 public interface Generator<T> {
6     T getKey();
7 }

Apple

复制代码
1 package com.xing.generic;
2 3 //实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
4 public class Apple implements Generator<String> {
5     @Override
6     public String getKey() {
7         return "hello generic";
8     }
9 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7  8         //实现类就是一个普通的类
 9         Apple apple = new Apple();
10         System.out.println(apple.getKey());//hello generic
11     }
12 13 }
复制代码

泛型方法

泛型方法的定义语法

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

泛型方法的使用

泛型方法是在调用方法的时候指明泛型的具体类型。

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7         GenericTest genericTest = new GenericTest();
 8         //泛型方法是在调用方法的时候指明泛型的具体类型
 9         String name = genericTest.get("小明");//根据自己传入的类型 确定范型方法的类型  方法为String类型
10         System.out.println(name);
11         Integer age = genericTest.get(20);//方法为Integer
12         System.out.println(age);
13 14         printType("s",100,true);//根据自己传入的类型 确定范型方法的类型 String  Integer  Boolean
15 16     }
17 18 19     //<T,E,V> 说明这个方法是范型方法而已    返回值与参数的泛型标识必须在泛型列表<T,E,V>中
20     //不会受泛型类的泛型标识影响
21     public <T,E,V> T get(T t) {
22         return t;
23     }
24 25 26     //静态的泛型方法,采用多个泛型类型
27     public static <T,E,K> void printType(T t, E e, K k) {
28         System.out.println(t + "\t" + t.getClass().getSimpleName());
29         System.out.println(e + "\t" + e.getClass().getSimpleName());
30         System.out.println(k + "\t" + k.getClass().getSimpleName());
31     }
32 33 34 }
复制代码

泛型方法注意事项

  • public与返回值中间< T >非常重要,可以理解为声明此方法为泛型方法。

  • 只有声明了< T >的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。

  • < T >表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。

  • 与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。

  • 泛型方法能使方法独立于泛型类而产生变化

  • 如果static方法要使用泛型能力,就必须使其成为泛型方法

泛型方法与可变参数

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7  8         print(1, 2, 3);//1 2 3
 9         print("小明", 2);// 小明 2
10         print(true);//true
11     }
12 13 14     public static <E> void print(E... e){
15         for (E e1 : e) {
16             System.out.println(e1);
17         }
18     }
19 }
复制代码

类型通配符

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7         Box<Integer> integerBox = new Box<>();
 8         integerBox.setGoods(100);
 9         print(integerBox);
10 11 12         
13         Box<Double> doubleBox = new Box<>();
14         doubleBox.setGoods(100.2);
15         // 报错  这个方法不能使用其它类型  只能使用Integer
16         // print(doubleBox);
17     }
18 19 20     //这个方法的参数只能传递Box<Integer>类型  不能传Box其它的类型 就算是其子类也不行  必须是Integer
21     public static void print(Box<Integer> integerBox){
22         Integer goods = integerBox.getGoods();
23         System.out.println(goods);
24     }
25 26 27     //泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型  com.xing.generic.Generic
28     // 这样重载会报错
29     // public static void print(Box<Double> doubleBox){
30     //     Double goods = doubleBox.getGoods();
31     //     System.out.println(goods);
32     // }
33 }
复制代码

 

为了解决方法只能传入一种类型的泛型,重载会报上述错误,不能解决问题,所以我们使用类型通配符

什么是类型通配符

  • 类型通配符一般是使用"?"代替具体的类型实参。

  • 类型通配符是类型实参,而不是类型形参。

复制代码
 1 package com.xing.generic;
 2  3  4 public class GenericTest {
 5  6     public static void main(String[] args) {
 7         Box<Integer> integerBox = new Box<>();
 8         integerBox.setGoods(100);
 9         print(integerBox);
10 11 12         Box<String> stringBox = new Box<>();
13         stringBox.setGoods("小明");
14         print(stringBox);
15     }
16 17 18     public static void print(Box<?> box){
19         Object goods = box.getGoods();
20         System.out.println(goods);
21     }
22 23 }
复制代码

类型通配符的上限

语法:

类/接口<? extends 实参类型>

要求该泛型的类型,只能是实参类型,或实参类型的子类类型

注意

  • 类型通配符上限的list是不能够填充元素的 采用上限不知道list中存放的是什么类型的数据

  • 遍历时写最高类型

复制代码
 1 package com.xing.generic;
 2  3 public class GenericTest {
 4  5     public static void main(String[] args) {
 6         Box<Number> numberBox = new Box<>();
 7         numberBox.setGoods(100);
 8         //参数为Box<Number>
 9         print(numberBox);
10 11 12         // Integer 继承自 Number类型
13         Box<Integer> integerBox = new Box<>();
14         integerBox.setGoods(100);
15         //参数为Box<Integer>
16         print(integerBox);
17     }
18 19 20     //类型通配符上限到Number类型 
21     //类型通配最大类型到Number类型  (这个方法的参数只能传Box泛型标识Number类型及其子类)
22     public static void print(Box<? extends Number> box){
23         Object goods = box.getGoods();
24         System.out.println(goods);
25     }
26 }
复制代码

测试

Person

1 package com.xing.generic;
2 3 public class Person {
4 }

Father

1 package com.xing.generic;
2 3 public class Father extends Person{
4 }

Son

1 package com.xing.generic;
2 3 public class Son extends Father{
4 }

GenericTest

复制代码
 1 package com.xing.generic;
 2  3 import java.util.ArrayList;
 4  5 public class GenericTest {
 6  7     public static void main(String[] args) {
 8         ArrayList<Person> person = new ArrayList<>();
 9         ArrayList<Father> father = new ArrayList<>();
10         ArrayList<Son> son = new ArrayList<>();
11         // print(person);  //报错 print方法最大类型只能到Father类型
12         print(father);
13         print(son);
14 15     }
16 17     //类型通配最大类型到Number类型  (之能传Number类型及其子类)
18     public static void print(ArrayList<? extends Father> list){
19         // 注意 类型通配符上限的list是不能够填充元素的   采用上限不知道list中存放的是什么类型的数据
20         // list.add(new Father());报错
21 22         //遍历时写最高类型
23         //遍历的类型为Father  因为最高类型为Father  其子类型Father也“兼容”
24         for (Father father : list) {
25             System.out.println(father);
26         }
27     }
28 29 }
复制代码

类型通配符的下限

语法:

类/接口<? super 实参类型>

要求该泛型的类型,只能是实参类型,或实参类型的父类类型

注意:

  • 遍历时写最高类型

  • 类型通配符下限的list是能够填充元素的,只能填充低类型及其子类的元素 因为低类型可以被高类型“兼容”

测试

Person

1 package com.xing.generic;
2 3 public class Person {
4 }

Father

1 package com.xing.generic;
2 3 public class Father extends Person{
4 }

Son

1 package com.xing.generic;
2 3 public class Son extends Father{
4 }

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 import java.util.ArrayList;
 5  6 public class GenericTest {
 7  8     public static void main(String[] args) {
 9         ArrayList<Person> person = new ArrayList<>();
10         ArrayList<Father> father = new ArrayList<>();
11         ArrayList<Son> son = new ArrayList<>();
12         print(person);
13         print(father);
14 15         // print(son);//报错 print方法最低类型只能到Father类型
16         
17     }
18 19     public static void print(ArrayList<? super Father> list){
20         // 注意 类型通配符下限的list是能够填充元素的,只能填充低类型Father及其子类的元素  因为低类型可以被高类型“兼容”
21         list.add(new Father());
22         list.add(new Son());
23         // list.add(new Person());报错  只能填充Father类型以下的
24 25 26         // 遍历时写最高类型
27         // 遍历时元素类型为Object(最高类型为Object,“兼容”所有子类)
28         for (Object o : list) {
29             System.out.println(o);
30         }
31 32     }
33 34 }
复制代码

测试:

复制代码
 1 package com.xing.generic;
 2  3  4 import java.util.Comparator;
 5 import java.util.TreeSet;
 6  7 public class GenericTest {
 8  9     public static void main(String[] args) {
10 11         // 按age排序
12         TreeSet<Father> treeSet = new TreeSet<>(new Comparator2());
13         treeSet.add(new Father("a",20));
14         treeSet.add(new Father("b",35));
15         treeSet.add(new Father("d",26));
16         treeSet.add(new Father("c",19));
17 18         for (Father father : treeSet) {
19             System.out.println(father);
20         }
21         /*
22             Father{age=19, name='c'}
23             Father{age=20, name='a'}
24             Father{age=26, name='d'}
25             Father{age=35, name='b'}
26          */
27 28 29         // 按name排序
30         TreeSet<Father> treeSet1 = new TreeSet<>(new Comparator1());
31         treeSet1.add(new Father("a",20));
32         treeSet1.add(new Father("b",35));
33         treeSet1.add(new Father("d",26));
34         treeSet1.add(new Father("c",19));
35 36         for (Father father : treeSet1) {
37             System.out.println(father);
38         }
39         /*
40             Father{age=20, name='a'}
41             Father{age=35, name='b'}
42             Father{age=19, name='c'}
43             Father{age=26, name='d'}
44          */
45 46         //TreeSet<Father> treeSet2 = new TreeSet<>(new Comparator3());
47         // 报错  public TreeSet(Comparator<? super E> comparator) 采用下限通配符
48 49     }
50 51 }
52 53 class Comparator1 implements Comparator<Person> {
54     @Override
55     public int compare(Person o1, Person o2) {
56         return o1.name.compareTo(o2.name);
57     }
58 }
59 60 class Comparator2 implements Comparator<Father> {
61     @Override
62     public int compare(Father o1, Father o2) {
63         return o1.age - o2.age;
64     }
65 }
66 67 class Comparator3 implements Comparator<Son> {
68     @Override
69     public int compare(Son o1, Son o2) {
70         return o1.level - o2.level;
71     }
72 }
复制代码

类型擦除

概念

泛型是Java 1.5版本才引进的概念,在这之前是没有泛型的,但是泛型代码能够很好地和之前版本的代码兼容。那是因为,泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为类型擦除。

分类:

  • 无限制类型擦除 转化为Object类型

复制代码
 1 Generic
 2 
 3 package com.xing.generic;
 4  5 /*
 6     泛型类的定义
 7     泛型标识相当于类型参数
 8     T 在创建Generic类的对象时,需指定具体的参数类型
 9  */
10 public class Generic<T> {
11     private T key;
12 13     public T getKey() {
14         return key;
15     }
16 17     public void setKey(T key) {
18         this.key = key;
19     }
20 21 22 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 import java.lang.reflect.Field;
 5  6 public class GenericTest {
 7  8     public static void main(String[] args) {
 9 10         Generic<Integer> generic = new Generic<>();
11         Class<? extends Generic> clazz = generic.getClass();
12         Field[] fields = clazz.getDeclaredFields();
13         for (Field field : fields) {
14             System.out.println(field.getName() + ":" + field.getType().getSimpleName());//key:Object   编译结束进行类型擦除  类型变为Object
15         }
16 17     }
18 19 }
复制代码
  • 有限制类型擦除 转化为上限类型

Generic

复制代码
 1 package com.xing.generic;
 2  3 /*
 4     泛型类的定义
 5     泛型标识相当于类型参数
 6     T 在创建Generic类的对象时,需指定具体的参数类型
 7  */
 8 public class Generic<T extends Number> {
 9     private T key;
10 11     public T getKey() {
12         return key;
13     }
14 15     public void setKey(T key) {
16         this.key = key;
17     }
18 19 20 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 import java.lang.reflect.Field;
 5  6 public class GenericTest {
 7  8     public static void main(String[] args) {
 9 10         Generic<Integer> generic = new Generic<>();
11         Class<? extends Generic> clazz = generic.getClass();
12         Field[] fields = clazz.getDeclaredFields();
13         for (Field field : fields) {
14             System.out.println(field.getName() + ":" + field.getType().getSimpleName());//key:Number   编译结束进行类型擦除  类型变为Number
15         }
16 17     }
18 19 }
复制代码
  • 擦除方法中类型定义的参数 只写< T >就擦除为Object类型

Generic

复制代码
 1 package com.xing.generic;
 2  3 import java.util.List;
 4  5 /*
 6     泛型类的定义
 7     泛型标识相当于类型参数
 8     T 在创建Generic类的对象时,需指定具体的参数类型
 9  */
10 public class Generic<T extends Number> {
11     private T key;
12 13     // 泛型方法
14     public <T extends List> T show(T t) {
15         return t;
16     }
17 18     public <E> E print(E e) {
19         return e;
20     }
21 22 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 import java.lang.reflect.Method;
 5  6 public class GenericTest {
 7  8     public static void main(String[] args) {
 9 10         Generic<Integer> generic = new Generic<>();
11         Class<? extends Generic> clazz = generic.getClass();
12 13         Method[] methods = clazz.getDeclaredMethods();
14         for (Method method : methods) {
15             System.out.println(method.getName()+":"+method.getReturnType().getSimpleName());
16         }
17         /*
18             print:Object
19             show:List
20          */
21     }
22 23 }
复制代码
  • 桥接方法

Generator

1 package com.xing.generic;
2 3 4 //泛型接口
5 public interface Generator<T> {
6     T getKey(T t);
7 }

GeneratorImpl

复制代码
 1 package com.xing.generic;
 2  3 //实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
 4 public class GeneratorImpl implements Generator<String> {
 5  6     @Override
 7     public String getKey(String s) {
 8         return s;
 9     }
10 }
复制代码

GenericTest

复制代码
 1 package com.xing.generic;
 2  3  4 import java.lang.reflect.Method;
 5  6 public class GenericTest {
 7  8     public static void main(String[] args) {
 9 10 11         Class<GeneratorImpl> clazz = GeneratorImpl.class;
12 13         Method[] methods = clazz.getDeclaredMethods();
14         for (Method method : methods) {
15             System.out.println(method.getName()+":"+method.getReturnType().getSimpleName());
16         }
17         /*
18             getKey:String
19             getKey:Object
20          */
21     }
22 }
复制代码

 


posted @   暴躁C语言  阅读(164)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示