Java 反射机制

举报
yd_221104950 发表于 2020/12/04 01:32:17 2020/12/04
【摘要】 反射机制可以帮助我们在动态运行时,获得任意一个类的所有的构造器、方法、变量。很多主流框架都使用了反射技术.像SSH框架就采用了xml做配置文件+反射技术。 为了更好说明反射技术,我们将利用TestObject类来演示: import java.util.HashMap; public class TestObject { private String myName;...

反射机制可以帮助我们在动态运行时,获得任意一个类的所有的构造器、方法、变量。很多主流框架都使用了反射技术.像SSH框架就采用了xml做配置文件+反射技术。
为了更好说明反射技术,我们将利用TestObject类来演示:

import java.util.HashMap;

public class TestObject { private String myName; private int myArg; public String hobby; public String schoolName; protected  String age; public String[] arr = new String[]{"hello","world"}; public TestObject(){ System.out.println("调用TestObject的无参构造方法"); this.myName = "wongkyunban"; this.myArg = 23; } public TestObject(String name){ System.out.printf("调用TestObject的有一个String型参数的构造方法:%s\n",name); this.myName = name; this.myArg = 21; } private TestObject(int arg){ System.out.printf("调用TestObject的有一个int型参数的构造方法:%d\n",arg); this.myName = "Jack"; this.myArg = arg; } public TestObject(int arg,String name){ System.out.printf("调用TestObject的有两个参数的构造方法"); this.myName = name; this.myArg = arg; } public String getMyName() { return myName; } public void setMyName(String myName) { this.myName = myName; } public int getMyArg() { return myArg; } public void setMyArg(int myArg) { this.myArg = myArg; } private void con(){ System.out.printf("hello,%s\n","您调用了一个私有方法"); } public void printHobby(){ System.out.printf("Hobby:%s\n",hobby); } protected void byebye(){ System.out.printf("Bye bye!\n"); } public void handleData(String arg1 ,HashMap<Integer,String> map){ System.out.printf("%s--->%s\n",arg1,map.get("name")); } private void say(String name){ System.out.printf("hello,%s\n",name); }
} 
  
 
  • 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
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

使用反射技术获得所有构造方法(包括私有的,非私有的)

默认权限的指的是没有修饰符修饰的。

方法 描述
public Constructor getConstructor(Class… parameterTypes) 获得指定的具有public访问权限的构造方法
public Constructor[] getConstructors() 获得所有的具有public访问权限的构造方法
public Constructor getDeclaredConstructor(Class… parameterTypes) 获得指定的构造方法,不管它的访问权限是什么。
public Constructor[] getDeclaredConstructors() 获得所有的构造方法,包括public, private,protected和默认权限的


示例代码:

 //获取构造函数 private void getConstructor(){ try { Class<?> clazz = Class.forName("TestObject"); //获得所有的具有public访问权限的构造方法 Constructor<?>[] constructors  = clazz.getConstructors(); System.out.printf("所有的具有public访问权限的构造方法:\n"); for(Constructor o:constructors){ System.out.printf("%s\n",o.toString()); } //获得指定的具有public访问权限的构造方法 Constructor<?> constructor = clazz.getConstructor(String.class); System.out.printf("获得指定的具有public访问权限的构造方法:\n"); System.out.printf("%s\n",constructor.toString()); //获得所有的构造方法,包括public, private,protected和默认权限的 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); System.out.printf("获得所有的构造方法,包括public, private,protected和默认权限的:\n"); for(Object o:declaredConstructors){ System.out.printf("%s\n",o.toString()); } //获得指定的构造方法,不管它的访问权限是什么 Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(int.class); System.out.printf("获得指定的构造方法,不管它的访问权限是什么:\n"); System.out.printf("%s\n",declaredConstructor.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } }

  
 
  • 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

使用获得的构造方法(包括私有的,非私有的)实例化对象。

注意事项: 如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到。

 //使用获得的构造函数,构造对象 public void useConstructor(){ try { Class<?> clazz = Class.forName("TestObject"); Constructor constructor = clazz.getConstructor(String.class); Object o = constructor.newInstance("Hello"); TestObject testObject = (TestObject) o; testObject.byebye(); Constructor privateConstructor = clazz.getDeclaredConstructor(int.class); //privateConstructor的访问权限不是public所以一定要执行下面这条语句 privateConstructor.setAccessible(true); Object o1 = privateConstructor.newInstance(88); TestObject testObject1 = (TestObject)o1; testObject1.byebye(); }catch (Exception e){ e.printStackTrace(); } }


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

使用反射获得所有的 Filed 变量

方法 描述
public Field[] getFields() 获得所有的具有public访问权限的字段
public Field getField(String name) 获得指定的具有public访问权限的字段
public Field[] getDeclaredFields() 获得所有字段,包括public, private,protected和默认权限的字段
public Field getDeclaredField(String name) 获得指定的字段,字段的访问权限包括public, private,protected和默认权限的

示例代码:

//获取所有字段 public void getMyField(){ try { Class<?> clazz = Class.forName("TestObject"); //获得所有的具有public访问权限的字段 Field[] fields = clazz.getFields(); System.out.printf("获得所有的具有public访问权限的字段:\n"); for(Field o:fields){ System.out.printf("%s\n",o.toString()); } //获得指定的具有public访问权限的字段 System.out.printf("获得指定的具有public访问权限的字段:\n"); Field field = clazz.getField("hobby"); System.out.printf("%s\n",field.toString()); //获得所有字段,包括public, private,protected和默认权限的字段 Field[] declaredfields = clazz.getDeclaredFields(); System.out.printf("获得所有的字段,包括public, private,protected和默认权限的字段:\n"); for(Field o:declaredfields){ System.out.printf("%s\n",o.toString()); } //获得指定的字段,字段的访问权限包括public, private,protected和默认权限的 System.out.printf("获得指定的字段,字段的访问权限包括public, private,protected和默认权限的:\n"); Field declaredField = clazz.getDeclaredField("myName"); System.out.printf("%s\n",declaredField.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } }

  
 
  • 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

使用获得的字段

注意:如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到

 //使用获得的字段 public void useMyfield(){ try { Class<?> clazz = Class.forName("TestObject"); Field field = clazz.getField("hobby");//有public权限的 TestObject object = new TestObject(); System.out.printf("%s\n",(String)field.get(object)); field.set(object,"PingPong"); System.out.printf("%s\n",(String)field.get(object)); Field privateField = clazz.getDeclaredField("myName"); privateField.setAccessible(true);//对于访问权限不是public的字段,要想访问,必须调用setAccessible。 System.out.printf("%s\n",(String)privateField.get(object)); privateField.set(object,"Wong"); System.out.printf("%s\n",(String)privateField.get(object)); }catch (Exception e){ e.printStackTrace(); } }

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

使用反射获取所有的 Method

方法 描述
public Method[] getMethods() 获得所有的具有public访问权限的方法
public Method getMethod(String name, Class<?>… parameterTypes) 获得指定的具有public访问权限的方法
public Method[] getDeclaredMethods() 获得所有方法,包括public, private,protected和默认权限的方法
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) 获得指定的方法,方法的访问权限包括public, private,protected和默认权限的

示例代码:

  //获取所有方法 public void getAllMethod(){ try { Class<?> clazz = Class.forName("TestObject"); //获得所有的具有public访问权限的方法 Method[] methods = clazz.getMethods(); System.out.printf("获得所有的具有public访问权限的方法:\n "); for(Object o:methods){ System.out.printf("%s\n",o.toString()); } //获得指定的具有public访问权限的方法 Method method = clazz.getMethod("setMyArg", int.class); System.out.printf("获得指定的具有public访问权限的方法:\n "); System.out.printf("%s\n",method.toString()); //获得所有方法,包括public, private,protected和默认权限的方法 Method[] declaredMethods = clazz.getDeclaredMethods(); System.out.printf("获得所有方法,包括public, private,protected和默认权限的方法:\n"); for(Object o:declaredMethods){ System.out.printf("%s\n",o.toString()); } //获得指定的方法,方法的访问权限包括public, private,protected和默认权限的 Method declaredMethod = clazz.getDeclaredMethod("say", String.class); System.out.printf("获得指定的方法,方法的访问权限包括public, private,protected和默认权限的:\n"); System.out.printf("%s\n",declaredMethod.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }

  
 
  • 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

使用已获得的方法

注意事项: 如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到。如果不用就会报如下错:

java.lang.IllegalAccessException: Class Main can not access a member of class TestObject with modifiers "private"

  
 
  • 1
 //使用已获得的方法 public void useMethod(){ try { Class<?> clazz = Class.forName("TestObject"); Method method = clazz.getMethod("handleData", String.class, HashMap.class);//有public权限的 TestObject testObject = new TestObject(); HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("name", "Kingkong"); method.invoke(testObject, "Tom", hashMap); Method privateMethod = clazz.getDeclaredMethod("con"); privateMethod.setAccessible(true);//对于访问权限不是public的方法,要想访问,必须调用setAccessible。 privateMethod.invoke(testObject); }catch (Exception e){ e.printStackTrace(); } }


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

使用反射操作数组

 //利用反射技术处理数组 public void handlArray() { String[] nameArr = new String[]{"Tom", "John", "Lucy", "Barkerly"}; Array.set(nameArr, 0, "Wongkyunban"); //修改数组的值 Class clazz = nameArr.getClass(); if (clazz.isArray()) { int len = Array.getLength(nameArr); for (int i = 0; i < len; i++) { Object object = Array.get(nameArr, i); String className = object.getClass().getName(); System.out.println("--> object=" + object + ",className=" + className); } } }

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

使用反射获得泛型类型

 //使用反射获得泛型类型 public void getGenericType(){ try { //Class<?> clazz = TestObject.class;与下面等价 Class<?> clazz = Class.forName("TestObject"); Method genericTypeMethod = clazz.getDeclaredMethod("handleData", String.class,HashMap.class); //获得所有的参数类型 Type[] genericParameterTypes = genericTypeMethod.getGenericParameterTypes(); //检验是否为空 if (null == genericParameterTypes || genericParameterTypes.length < 1) { return; } //取方法第2个参数,获得泛型参数的类型 ParameterizedType parameterizedType = (ParameterizedType)genericParameterTypes[1]; Type rawType = parameterizedType.getRawType(); System.out.printf("--->raw type:%s\n",rawType); //取得第二个泛型参数类型 Type[] actualTypeArgs = parameterizedType.getActualTypeArguments(); if(actualTypeArgs == genericParameterTypes || actualTypeArgs.length < 1){ return; } //打印出每一个类型 for (int i = 0; i < actualTypeArgs.length; i++){ Type type = actualTypeArgs[i]; System.out.printf("--->Type:%s\n",type); } }catch (Exception e){ e.printStackTrace(); } }

  
 
  • 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

获得 Metho,Field,Constructor 的访问权限 ( public,private,ptotected 等)

 //获得Metho,Field,Constructor 的访问权限 public void showPermmit(){ try { Class<?> clazz = Class.forName("TestObject"); Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor:constructors){ int modifier = constructor.getModifiers(); System.out.printf("构造器%s,权限是%s\n",constructor.toString(), Modifier.toString(modifier)); } System.out.printf("\n\n"); Field[] fields = clazz.getDeclaredFields(); for (Field field:fields){ int modifier = field.getModifiers(); System.out.printf("字段%s,权限是%s\n",field.toString(), Modifier.toString(modifier)); } System.out.printf("\n\n"); Method[] methods = clazz.getDeclaredMethods(); for (Method method:methods){ int modifier = method.getModifiers(); System.out.printf("方法%s,权限是%s\n",method.toString(), Modifier.toString(modifier)); } }catch (Exception e){ e.printStackTrace(); } }


  
 
  • 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

演示demo

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

原文链接:blog.csdn.net/weixin_40763897/article/details/89139489

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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