java.lang.reflect提供类和接口,以获取关于类和对象的反射信息。在安全限制内,反射允许编程访问关于加载类的字段、方法和构造方法的信息,并允许使用反射字段、方法和构造方法对对象上的基本对等项进行操作。
java.lang.reflect包下常用的类有
- Field 类:用于操作类的成员变量;
- Method类:用于操作类的方法;
- Constructor 类:用于操作类的构造方法;
- Array类:提供了动态创建数组,以及访问数组的元素的静态方法;
java.lang.reflect一般都是配合java.lang.Class一起使用。
常用的方法有
getName():获得类的完整名字;
getFields():获得类的public类型的成员变量;
getDeclaredFields():获得类的所有成员变量;
getMethods():获得类的public类型的方法;
getDeclaredMethods():获得类的所有方法;
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型;
getConstructors():获得类的public类型的构造方法;
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型;
实例
stu.java
package cn.iborder.javaBean;
import java.util.Date;
public class Stu {
public int id;
private String name;
private int age;
public Stu(){
super();
}
public Stu(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
private Stu(String name) {
super();
this.id = 88888;
this.name = name;
this.age = 100;
}
private int getId() {
return id;
}
private void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void sayHello(String name,Date date) {
System.out.println(date+":"+this.id+this.name+"你好,我是"+name);
}
}
TestReflect2.java
package cn.iborder.test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class TestReflect2 { public static void main(String[] args) throws ClassNotFoundException { // TODO Auto-generated method stub Class class1 = Class.forName("cn.iborder.javaBean.Stu"); System.out.println("类名:"+class1.getName()); System.out.println("包名:"+class1.getPackage()); System.out.println("父类名:"+class1.getSuperclass().getName()); System.out.println("========成员变量========"); //成员变量 System.out.println("xxxx全部成员变量xxxx"); Field[] fields = class1.getDeclaredFields();//获得所有成员变量 for (Field field : fields) { System.out.println(field.getType().getSimpleName() +" "+ field.getName()); } System.out.println("xxxx公有成员变量xxxx"); Field[] fields1 = class1.getFields(); for (Field field : fields1) { System.out.println(field.getType().getSimpleName() +" "+ field.getName()); } System.out.println("========成员方法========"); //成员方法 System.out.println("xxxx全部成员方法xxxx"); Method[] methods = class1.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()+"()"); } System.out.println("xxxx公有成员方法xxxx"); Method[] methods1 = class1.getMethods(); for (Method method : methods1) { System.out.println(method.getName()+"()"); } System.out.println("========构造方法========"); //构造方法 System.out.println("xxxx全部构造方法xxxx"); Constructor[] constructors = class1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor.getName()+"()"); } System.out.println("xxxx公有构造方法xxxx"); Constructor[] constructors1 = class1.getConstructors(); for (Constructor constructor : constructors1) { System.out.println(constructor.getName()+"()"); } } }
运行结果
类名:cn.iborder.javaBean.Stu 包名:package cn.iborder.javaBean 父类名:java.lang.Object ========成员变量======== xxxx全部成员变量xxxx int id String name int age xxxx公有成员变量xxxx int id ========成员方法======== xxxx全部成员方法xxxx getAge() setAge() sayHello() setId() getName() getId() setName() xxxx公有成员方法xxxx getAge() setAge() sayHello() getName() setName() getClass() hashCode() equals() toString() notify() notifyAll() wait() wait() wait() ========构造方法======== xxxx全部构造方法xxxx cn.iborder.javaBean.Stu() cn.iborder.javaBean.Stu() cn.iborder.javaBean.Stu() xxxx公有构造方法xxxx cn.iborder.javaBean.Stu() cn.iborder.javaBean.Stu()
通过反射创建新的类对象,有两种方式:
Class.newInstance() 只能够调用无参构造函数(要求被调用的构造函数是可见的,也即必须是public类型的; );
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数(在特定的情况下,可以调用私有的构造函数)。
实例
TestReflect3.java
package cn.iborder.test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date; import cn.iborder.javaBean.Stu; public class TestReflect3 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { // TODO Auto-generated method stub Class<?> class1 = Class.forName("cn.iborder.javaBean.Stu"); //调用public类型无参构造函数创建对象 Stu stu1 = (Stu) class1.newInstance(); System.out.println(stu1.getName()); //调用public类型有参构造函数创建对象 Constructor<?> constructor = class1.getConstructor(new Class[]{int.class, String.class, int.class}); Stu stu2 = (Stu) constructor.newInstance(new Object[]{10086,"李四",23}); System.out.println(stu2.getName()); Object object = constructor.newInstance(new Object[]{10010,"王五",13}); Method method = class1.getMethod("sayHello", new Class[]{String.class,Date.class}); method.invoke(object, new Object[]{"乔布斯",new Date()}); Field field = class1.getField("id"); field.set(object, 10086); method.invoke(object, new Object[]{"乔布斯",new Date()}); //调用private类型有参构造函数创建对象 Constructor<?> constructor2 = class1.getDeclaredConstructor(new Class[]{String.class}); constructor2.setAccessible(true);// 功能是启用或禁用安全检查,true表示允许调用 Object object2 = constructor2.newInstance(new Object[]{"李彦宏"}); method.invoke(object2, new Object[]{"乔布斯",new Date()}); } }
运行结果
null
李四
Fri Oct 21 17:01:12 CST 2016:10010王五你好,我是乔布斯
Fri Oct 21 17:01:13 CST 2016:10086王五你好,我是乔布斯
Fri Oct 21 17:01:13 CST 2016:88888李彦宏你好,我是乔布斯
Accessable属性是继承自AccessibleObject 类. 功能是启用或禁用安全检查。
AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获得字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。
在反射对象中设置 accessible 标志允许具有足够特权的复杂应用程序(比如 Java Object Serialization 或其他持久性机制)以某种通常禁止使用的方式来操作对象。
public void setAccessible(boolean flag) throws SecurityException