Java学习中关于反射

xiaoxiao2021-02-28  96

同过反射机制可以在程序中访问已经装载到JVM(JVM是Java虚拟机,所有Java程序都在Java虚拟机中运行)中的Java对象的描述,实现访问、检测、和修改描述Java对象本身信息的功能。

也就是说Java反射机制可以在程序运行的时候得知它们的各种属性,行为,和状态,并且可以改变它。

访问构造方法

访问构造方法的方法:

getConstructors()

getConstructors(class<?>...parameterTypes)

getDeclaredConstructors()

getDeclaredConstructors(class<?>...parameterTypes)

这些方法都返回Constructor类型的对象或数组,每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法。

// 访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问如:

// objectClass.getDeclaredConstructor(String.class, int.class);

// objectClass.getDeclaredConstructor(new Class[]{String.class, int.class});

Constructor类中提供的常用方法如下:

isVarArgs()                                  查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false

getParameterTypes()                  按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型

etExceptionTypes()                     以Class数组的形式获得该构造方法可能抛出的异常类型

newInstance(Object...initargs)    通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参的构造方法

setAccessible(boolean flag)        如果该构造方法的权限为private,默认为不允许通过反射利用newInstance(Object...initargs)方法创建对象。如果先执行该方法,并将入口参数设置为true,则允许创建

getModifiers()                              获得可以解析出该构造方法所采用修饰符的整数。

代码如下:

package reflect; public class E01 { String s; int i, i2, i3; private E01(){ } protected E01(String s, int i) { this.s = s; this.i = i; } public E01(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); } } // 下面的代码会用到上面的 package reflect; import java.lang.reflect.Constructor; public class M01 { public static void main(String[] args) { E01 example = new E01("10","20","30"); Class<? extends E01> ec = example.getClass(); //获得所有构造方法。 Constructor[] declaredConstructors = ec.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]); } E01 example2 = null; while(example2 == null) { try { //如果该成员变量的访问权限设为private,则抛出异常,即不允许访问 if(i == 2) { //通过执行默认没有参数的构造方法创建对象 example2 = (E01)constructor.newInstance(); } else if(i == 1) { //通过执行具有可变数量参数的构造方法创建对象 example2 = (E01)constructor.newInstance("7",5); } else { Object[] parameters = new Object[] {new String[] {"100","200","300"}}; example2 = (E01)constructor.newInstance(parameters); //设为允许访问 } } catch (Exception e) { System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法"); constructor.setAccessible(true); } } if(example2 != null) { example2.print(); System.out.println(); } } } }

访问成员变量

访问成员变量的方法:

getFields();

getField(String name);

getDeclaredFields();

getDeclaredField(String name);

这些方法都返回一个Field类型的对象或数组,每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。

如果是访问指定的成员变量,可以通过成员变量的名称来访问。例如访问一个名称为birthday的成员变量,访问方法如下:

object.getDeclaredFiled("birrthday");

Field类中提供的常用方法此处省略。

代码如下:

package reflect; public class E02 { int i; public float f; protected boolean b; private String s; } package reflect; import java.lang.reflect.Field; public class M02 { public static void main(String[] args) { E02 e = new E02(); Class eC = e.getClass(); Field[] declaredFields = eC.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) { try { isTurn = false; System.out.println("修改前的职位:"+ field.get(e)); if(fieldType.equals(int.class)) { System.out.println("利用方法setint()修改成员变量的值"); field.setInt(e, 168); //判断成员变量的类型是否为float型 } else if(fieldType.equals(float.class)) { System.out.println("利用方法setfloat()修改成员变量的值"); field.setFloat(e, 99.9f); } else if(fieldType.equals(boolean.class)) { System.out.println("利用方法setboolean()修改成员变量的值"); field.setBoolean(e, true); } else { System.out.println("利用方法set()修改成员变量的值"); field.set(e, "MWQ"); } System.out.println("修改后的值为:" + field.get(e)); } catch (Exception e2) { System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法"); field.setAccessible(true); isTurn = true; } } System.out.println(); } } }

访问方法

访问方法的方法:

getMethods();

getMethod(String name, Class<?>...parameterTypes);

getDeclaredMethods();

getDeclaredMethod(String name, Class<?>...parameterTypes);

这些方法返回的都是Method类型的对象或者数组,每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。

如果访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如访问一个名称为print、入口参数类型依次为String和int型的方法,通过下面两种方式均可实现:

objectClass.getDecalaredMethod("print", String.class, int.class);

objectClass.getDecalaredMethod("print", new Class[]{String.class, int.class});

Method类中常用方法此处省略。

代码如下:

package reflect; public class E03 { 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 < stringBuffer.length(); i++) { stringBuffer.append(strings[i]); } return stringBuffer.toString(); } } package reflect; import java.lang.reflect.Method; public class M03 { public static void main(String[] args) { E03 e = new E03(); Class<? extends E03> eC = e.getClass(); Method[] declaredMethods = eC.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[] exception = method.getExceptionTypes(); for(int j = 0; j < exception.length; j++) { System.out.println("" + exception[j]); } boolean isTurn = true; while(isTurn) { try { isTurn = false; if("staticMethod".equals(method.getName())) { method.invoke(e); } else if("publicMethod".equals(method.getName())) { System.out.println("返回值为:"+method.invoke(e, 168)); } else if("protectedMethod".equals(method.getName())) { System.out.println("返回值为:"+method.invoke(e, "7", 5)); } else if("privateMethod".equals(method.getName())) { Object[] parameters = new Object[] {new String[] {"M","W","Q"}}; System.out.println("返回值为:"+method.invoke(e, parameters)); } } catch (Exception exception2) { System.out.println("在执行方法时抛出异常,下面执行setAccessible()方法!"); method.setAccessible(true); isTurn = true; } } System.out.println(); } } }

转载请注明原文地址: https://www.6miu.com/read-56656.html

最新回复(0)