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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本