亲宝软件园·资讯

展开

Java的反射

红尘少年 人气:0
# Java的反射 ### Class类 在此之前,我们必须知道一句话,“java之中的一切都可以看作一个对象”。类是对象的抽象,而Class则是类的抽象,即任何一个类都是Class的实例对象。另外注意区别Class类和class关键字。Class类下面有很多方法,例如getConstructors() (包括其一些相似作用的方法这里以及后面不再列举,例如getDeclaredConstructor()等等),getFields(),getMethods();而它们会分别返回Constructor类型、Filed类型、Method类型的对象或者数组。Class类的构造方法是私有的,当一个类被加载时,JVM(java虚拟机)会自动通过Class的私有构造方法实例化一个Class对象,而我们没有办法通过Class的构造方法去实例化Class。而我们可以通过以下三种方法来获得Class的实例化对象; 1. 类名.forName("具体路径 包名.类名"); 2. 类名.class; 3. 对象.getClass(); 获得了Class的实例化对象,我们就可以获得类的很多信息,例如权限修饰符,参数列表,类名,成员变量,成员方法等等。 ### Constructor类 每个Constructor对象都代表一个构造方法,利用Constructor对象可以操作相应的构造方法。下面时Constructor类常用的方法以及它的作用; 1. isVarArgs(),查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false;方法原型:public boolean isVarArgs(); 2. getName(),以字符串的形式返回该构造方法的名字。方法原型:public String getName(); 3. getParameterTypes(),按照声明顺序以Class数组的形式获得该构造方法的各个参数类型。方法原型:public Class[] getParameterTypes(); 4. getExceptionTypes(),以Class数组的形式获得该构造方法可能抛出的异常类型。方法原型:public Class[] getExceptionTypes(); 5. newInstance(),通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法。函数原型:public T newInstance(Object... initargs),T表示返回的是一个Objec类的对象;
`注:Class.newInstance和Constructor.newInstance的有区别;Constructor的该方法能够使用有参数的构造方法,而Class下的该方法只能够使用无参默认构造方法。` 6. setAccessible(),如果该构造方法的权限为private,默认不允许通过反射利用newInstance()方法创建对象;如果先执行该方法并将入口参数设为true,则允许创建。方法原型:public void setAccessible(boolean flag); 7.getModifiers(),获得可以解析出该构造方法所采用的修饰符的整数(利用Modifier类下的toString方法可以转换成字符串)。方法原型:public int getModifiers()。 > 下面介绍几个Modifier类常用的方法;
>isPublic(int mod);
>isProtected(int mod);
>isPrivate(int mod);
>isStatic(int mod);
>isFinal(int mod);
>toString(int mod);
>这几种方法的作用都显而易见,不再赘述。 下面看代码示例: ``` //代码示例 Main类 import java.lang.reflect.*; public class Main_01 { public static void main(String[] args) { Example_01 example = new Example_01("10", "20", "30"); Class exampleC = example.getClass(); Constructor[] declaredConstructors = exampleC.getDeclaredConstructors(); for (int i = 0; i < declaredConstructors.length; i++) { Constructor constructor = declaredConstructors[i]; System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs()); System.out.println("该构造方法的入口参数类型依次为:"); Class[] parameterTypes = constructor.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } System.out.println("该构造方法可能抛出的异常类型为:"); Class[] exceptionTypes = constructor.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } Example_01 example2 = null; while (example2 == null) { try { if (i == 2) example2 = (Example_01) constructor.newInstance(); else if (i == 1) example2 = (Example_01) constructor.newInstance("7", 5); else { Object[] parameters = new Object[] { new String[] { "100", "200", "300" } }; example2 = (Example_01) constructor .newInstance(parameters); } } catch (Exception e) { System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法"); constructor.setAccessible(true); } } if(example2!=null){ example2.print(); System.out.println(); } } } } ``` ``` //代码示例 Example类 public class Example_01 { String s; int i, i2, i3; private Example_01() { } protected Example_01(String s, int i) { this.s = s; this.i = i; } public Example_01(String... strings) throws NumberFormatException { if (0 < strings.length) i = Integer.valueOf(strings[0]); if (1 < strings.length) i2 = Integer.valueOf(strings[1]); if (2 < strings.length) i3 = Integer.valueOf(strings[2]); } public void print() { System.out.println("s=" + s); System.out.println("i=" + i); System.out.println("i2=" + i2); System.out.println("i3=" + i3); } } ``` 这是运行结果截图:
![](https://img2020.cnblogs.com/blog/1974002/202004/1974002-20200402001703670-849536456.png) ### Filed类 每个Field对象都代表一个成员变量,利用Field对象可以操控相应的成员变量。下面是Field类的一些常用的方法以及作用; 1. getName(),获得该成员变量的名称。方法原型:public String getName(); 2. getType(),获得表示该成员变量类型的Class对象。方法原型:public Class getType(); 3. getModifiers(),获得可以解析出该成员变量所采用修饰符的整数。方法原型:public int getModifiers(); 4. get(Object obj),获得指定对象obj中成员变量的值,返回类型为Object型。方法原型:public Object get(Object obj); 5. set(Object obj,Object value),将指定对象obj中成员变量的值设定为value; `还有具体到各种类型的get set方法,不再一一介绍。另外说明:Object对象指的是已经实例化的反射对象。` 下面是代码示例: ``` //代码示例 Main类 import java.lang.reflect.*; public class Main_02 { public static void main(String[] args) { Example_02 example = new Example_02(); Class exampleC = example.getClass(); // 获得所有成员变量 Field[] declaredFields = exampleC.getDeclaredFields(); for (int i = 0; i < declaredFields.length; i++) { Field field = declaredFields[i]; // 遍历成员变量 // 获得成员变量名称 System.out.println("名称为:" + field.getName()); Class fieldType = field.getType(); // 获得成员变量类型 System.out.println("类型为:" + fieldType); boolean isTurn = true; while (isTurn) { // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问 try { isTurn = false; // 获得成员变量值 System.out.println("修改前的值为:" + field.get(example)); // 判断成员变量的类型是否为int型 if (fieldType.equals(int.class)) { System.out.println("利用方法setInt()修改成员变量的值"); field.setInt(example, 168); // 为int型成员变量赋值 // 判断成员变量的类型是否为float型 } else if (fieldType.equals(float.class)) { System.out.println("利用方法setFloat()修改成员变量的值"); // 为float型成员变量赋值 field.setFloat(example, 99.9F); // 判断成员变量的类型是否为boolean型 } else if (fieldType.equals(boolean.class)) { System.out.println("利用方法setBoolean()修改成员变量的值"); // 为boolean型成员变量赋值 field.setBoolean(example, true); } else { System.out.println("利用方法set()修改成员变量的值"); // 可以为各种类型的成员变量赋值 field.set(example, "MWQ"); } // 获得成员变量值 System.out.println("修改后的值为:" + field.get(example)); } catch (Exception e) { System.out.println("在设置成员变量值时抛出异常," + "下面执行setAccessible()方法!"); field.setAccessible(true); // 设置为允许访问 isTurn = true; } } System.out.println(); } } } ``` ``` //代码示例 Example类 public class Example_02 { int i; public float f; protected boolean b; private String s; } ``` 下面是运行结果:
![](https://img2020.cnblogs.com/blog/1974002/202004/1974002-20200402001716711-1337000704.png) ### Method类 每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。下面是Method类的一些常用的方法以及作用; 1. getName(),获得该方法的名称。方法原型:public String getName(); 2. getParameterTypes(),按照声明的顺序以Class数组的形式获得该方法的各个参数的类型。方法原型:public Class[] getParameterTypes(); 3. getReturnType(),以Class对象的形式返回该方法的返回类型。方法原型:public Class getReturnType(); 4. getExceptionTypes(),以Class数组的形式获得该方法可能抛出的异常。方法原型:public Class getExceptionTypes(); 5. invoke(Object obj,Object···args),利用指定参数args执行指定对象obj中的该方法,返回值类型为Object型。方法原型:public Object invoke(Object obj, Object... args); 6. isVarArgs(),同Constructor; 7. getModifiers(),同上。 下面是代码示例: ``` //代码示例 Main类 import java.lang.reflect.*; public class Main_03 { public static void main(String[] args) { Example_03 example = new Example_03(); Class exampleC = example.getClass(); // 获得所有方法 Method[] declaredMethods = exampleC.getDeclaredMethods(); for (int i = 0; i < declaredMethods.length; i++) { Method method = declaredMethods[i]; // 遍历方法 System.out.println("名称为:" + method.getName()); // 获得方法名称 System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs()); System.out.println("入口参数类型依次为:"); // 获得所有参数类型 Class[] parameterTypes = method.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } // 获得方法返回值类型 System.out.println("返回值类型为:" + method.getReturnType()); System.out.println("可能抛出的异常类型有:"); // 获得方法可能抛出的所有异常类型 Class[] exceptionTypes = method.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } boolean isTurn = true; while (isTurn) { // 如果该方法的访问权限为private,则抛出异常,即不允许访问 try { isTurn = false; if("staticMethod".equals(method.getName())) method.invoke(example); // 执行没有入口参数的方法 else if("publicMethod".equals(method.getName())) System.out.println("返回值为:" + method.invoke(example, 168)); // 执行方法 else if("protectedMethod".equals(method.getName())) System.out.println("返回值为:" + method.invoke(example, "7", 5)); // 执行方法 else if("privateMethod".equals(method.getName())) { Object[] parameters = new Object[] { new String[] { "M", "W", "Q" } }; // 定义二维数组 System.out.println("返回值为:" + method.invoke(example, parameters)); } } catch (Exception e) { System.out.println("在执行方法时抛出异常," + "下面执行setAccessible()方法!"); method.setAccessible(true); // 设置为允许访问 isTurn = true; } } System.out.println(); } } } ``` ``` //代码示例 Example public class Example_03 { static void staticMethod() { System.out.println("执行staticMethod()方法"); } public int publicMethod(int i) { System.out.println("执行publicMethod()方法"); return i * 100; } protected int protectedMethod(String s, int i) throws NumberFormatException { System.out.println("执行protectedMethod()方法"); return Integer.valueOf(s) + i; } private String privateMethod(String... strings) { System.out.println("执行privateMethod()方法"); StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < strings.length; i++) { stringBuffer.append(strings[i]); } return stringBuffer.toString(); } } ``` 下面是运行结果图:
![](https://img2020.cnblogs.com/blog/1974002/202004/1974002-20200402001734467-1807792675.png) 未完待更……2020-4-2

加载全部内容

相关教程
猜你喜欢
用户评论