为什么要了解java的反射机制
java的反射机制主要是更深入地控制程序的运行过程,可以在程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程。
一.反射
通过JAVA的反射机制,可以访问装载到JVM中的JAVA对象的描述,实现访问检测,修改描述JAVA对象本身信息的功能。
JTextField textfield =new JTextField();
class textFieldC=textField.getClass();
1.1访问构造方法
通过一组方法来访问构造方法:返回Constructor类型的对象或者数组,每个constructor对象代表一个构造方法,利用constructor对象可以操纵相应的构造方法。
具体的constructor类型的介绍可以参考这篇:添加链接描述
下面举个例子:
测试类通过反射访问Demo1类中的所有构造方法,并且将该构造方法是否允许带有可变数量的参数,入口参数类型和可能抛出的异常类型信息输出到控制台。
import java.lang.reflect.*;
import javax.lang.model.type.DeclaredType;
import javax.net.ssl.ExtendedSSLSession;
import FANHE.Demo1;
public class ConstructorDemo1 {
public static void main(String[]args) {
Demo1 demo1=new Demo1("10","20","30");
Class<?extends Demo1>demo1Class=demo1.getClass();
Constructor[]declaredConstructors=demo1Class.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]);
}
Demo1 d2=null;
while(d2==null) {
try {if(i==2)
d2=(Demo1)constructor.newInstance();
else if(i==1)
d2=(Demo1)constructor.newInstance("7",5);
else {
Object[]parameters=new Object[] {new String[] {"100","200","300"}};
d2=(Demo1)constructor.newInstance(parameters);
}
}catch(Exception e) {
System.out.println("抛出异常");
constructor.setAccessible(true);
}
}
if(d2!=null) {
d2.print();
System.out.println();
}
}
}
}
其中Demo1类的构造如下:
public class Demo1 {
String s;
int i,i2,i3;
private Demo1() {}
protected Demo1(String s,int i) {
this.s=s;
this.i=i;
}
public Demo1(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);
}
}
程序运行结果如下:
1.2访问成员变量
通一组方法来访问类的成员变量:返回Field类型的对象或者数组,每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。
简单返回成员变量的名称为例:
import java.lang.reflect.Field;
public class FieldDemo {
public static void main(String[]args) {
Demo2 example=new Demo2();
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();
}
}
}
其中成员变量的定义如下:
public class Demo2 {
int i;
public float f;
protected boolean b;
private String s;
}
输出结果如下:
1.3访问成员方法
import Fanshe2.Demo3;
import java.lang.reflect.*;
public class MethodDemo {
public static void main(String[]args) {
Demo3 demo=new Demo3();
Class demoClass=demo.getClass();
Method[]declaredMethod=demoClass.getDeclaredMethods();
for(int i=0;i<declaredMethod.length;i++) {
Method method=declaredMethod[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) {
try {
isTurn=false;
if("staticMethod".equals(method.getName()))
method.invoke(demo);
else if("publicMethod".equals(method.getName()))
System.out.println("返回值"+method.invoke(demo, 168));
else if("protectedMethod".equals(method.getName()))
System.out.println("返回值为"+method.invoke(demo, "7",5));
else if ("privateMethod".equals(method.getName())) {
Object[]parameters=new Object[] {new String[]{"M","W","Q"}};
System.out.println("返回值为"+method.invoke(demo, parameters));
}
}catch(Exception e) {
System.out.println("在执行方法时抛出异常");
method.setAccessible(true);
isTurn=true;
}
}
System.out.println();
}
}
}
定义的demo3代码块:
public class Demo3 {
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();
}
}
在反射中执行可变数量的参数的构造方法时,需要将入口参数定义成二维数组。Method类的常用方法请自行查阅。