Reflection 是 Java 程序开发语言的重要特征之一,是学习Java必须知识点。
Java.lang.Class和Java.lang.reflect包下的API,用于表示或者处理当前JVM中的类,接口和对象。
Java反射的主要功能:
确定一个对象的类
取出类的modifiers,数据成员,方法,构造器,和超类.
找出某个接口里定义的常量和方法说明.
创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象).
取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到.
在运行时刻调用动态对象的方法.
创建数组,数组大小和类型在运行时刻才确定,也能更改数组成员的值.
Class类是Java反射的基础,Class类表示正在运行的java应用程序中的类和接口。Class只有私有的构造函数。Class类在加载类时由Java虚拟机以及调用类加载器中的 defineClass方法自动创建的。只在内存中存在一份加载类的Class类。
三种方式得到某个Java类的Class类,以java.lang.String为例:
String s = "aaa";
Class cls1 = s.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
if (cls1 == cls2) {
System.out.println("cls1 == cls2");
}
if (cls2 == cls3) {
System.out.println("cls2 == cls3");
}
为什么他们三个会==呢?因为他们描述的都是同一个类java.lang.String类。
Class类还有很多方法,配合java.lang.reflect包下的一些API可以实现更多的功能。
一个javabean
package org.legend.reflect; public class UserInfo { private String userName; private Integer age; public String school; public UserInfo() { } public UserInfo(String name, Integer age, String shool) { this.userName = name; this.age = age; this.school = shool; } public UserInfo(String name, Integer age) { this.userName = name; this.age = age; } public String getInfo(String n, Integer i) { return "success" + n + i; } public void getMyInfo(String mName, String mBirth, Integer age) { System.out.println("我是一个来自" + mBirth + "的名叫:" + mName + "的" + age + "岁的选手"); } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
一个操作类
package org.legend.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * 反射操作类 */ public class GetMyInfo { public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class mclass = Class.forName("org.legend.reflect.UserInfo"); System.out.println("------------输出类名-----------------------"); System.out.println(mclass.getName()); System.out.println(mclass.getSimpleName()); //基础类的简称 //获取属性(字段) System.out.println("------------输出所有属性--------------------"); Field[] fileds=mclass.getDeclaredFields(); //得到所声明的所有的字段,包括公共,保护,默认(包)和私有变量,但不包括继承的字段。 //Field[] fileds = mclass.getFields(); //得到所声明的所有可访问的公共字段。 for(Field field:fileds) { String fieldName = field.getName(); //属性名称 int fieldFangWen = field.getModifiers(); //属性访问权限修饰符 Class fieldType = field.getType(); //属性类型 System.out.println(Modifier.toString(fieldFangWen)+" "+fieldType.getSimpleName()+" "+fieldName); } //获取方法 System.out.println("------------输出所有方法--------------------"); Method [] methods=mclass.getDeclaredMethods(); //Method[] medthods = mclass.getMethods(); for(Method method:methods) { String methodName = method.getName(); //方法名称 int methodFangWen = method.getModifiers(); //访问修饰符 Class methodRetrunType = method.getReturnType();//返回类型 Class [] methodParameter = method.getParameterTypes();//方法的参数列表 System.out.print(Modifier.toString(methodFangWen)+" "+methodRetrunType.getSimpleName()+" "+methodName+"("); for(int k=0;k<methodParameter.length;k++) { String parameterName=methodParameter[k].getSimpleName(); if(k!=methodParameter.length-1) { System.out.print(parameterName+" arg"+k+","); } else System.out.print(parameterName+" arg"+k); } System.out.println(");"); } //获取构造 System.out.println("------------输出所有构造器--------------------"); Constructor[]constructors = mclass.getConstructors(); for(Constructor constructor:constructors) { String constructorName = constructor.getName(); Class[] constructorParameter = constructor.getParameterTypes(); System.out.print(mclass.getSimpleName()+" "+constructorName.substring(constructorName.lastIndexOf(".")+1, constructorName.length())+"("); for(int h=0;h<constructorParameter.length;h++) { String parameterName = constructorParameter[h].getSimpleName(); if(h!=constructorParameter.length-1) System.out.print(parameterName+" arg"+h+","); else System.out.print(parameterName+" arg"+h); } System.out.println(");"); } //如何执行指定的方法 System.out.println("------------反射执行方法--------------------"); String name ="getMyInfo"; Class[] parameterTypes = new Class[3]; parameterTypes[0]= String.class; parameterTypes[1]= String.class; parameterTypes[2]= Integer.class; Method me = mclass.getDeclaredMethod(name, parameterTypes); Object obj = mclass.newInstance(); Object[] arg = new Object[3]; arg[0]="范晶晶"; arg[1]="AAA风景区"; arg[2]=new Integer(18); me.invoke(obj, arg); } }
反射的应用很多,很多框架都有用到
spring 的 ioc/di 也是反射....
javaBean和jsp之间调用也是反射....
struts的 FormBean 和页面之间...也是通过反射调用....
JDBC 的 classForName()也是反射.....
hibernate的 find(Class clazz) 也是反射....
反射还有一个不得不说的问题,就是性能问题,大量使用反射系统性能大打折扣。怎么使用使你的系统达到最优就看你系统架构和综合使用问题啦,这里就不多说了。。。