反射机制
获取运行时类的完整结构
- 通过反射获取运行时类的完整结构包括:Field、Method、Construct、SupperClass、interface、Annotation
- 类的默认无参构造是私有的,用private修饰
public class Demo08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.phx.reflection.Users");
System.out.println(c1);
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println();
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Field age = c1.getField("age");
System.out.println(age);
Field name = c1.getDeclaredField("name");
System.out.println(name);
System.out.println("===============");
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("===============");
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("===============");
Method setName = c1.getMethod("setName", String.class);
System.out.println(setName);
Method getName = c1.getDeclaredMethod("getName", null);
System.out.println(getName);
Method sayHello = c1.getDeclaredMethod("sayHello", String.class);
System.out.println(sayHello);
System.out.println("===============");
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
Constructor constructor = c1.getConstructor(String.class, String.class, int.class);
System.out.println(constructor);
Constructor declaredConstructor = c1.getDeclaredConstructor(null);
System.out.println(declaredConstructor);
}
}
class Users{
private Users(){}
public Users(String name,String sex,int age){
this.name=name;
this.sex=sex;
this.age=age;
}
private String name="张三";
private String sex="男";
public int age=20;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private void sayHello(String name){
System.out.println("Hello"+name);
}
}
调用运行时类的指定结构
- 创建类的对象:调用Class对象的newInstance()方法
- 必须要有一个无参的构造器
- 类的构造器的访问权限需要足够
- 如果是有参构造
1、通过getConstructor(Class<?>… parameterTypes)取得本类的指定形参类型的构造器
2、向构造器形参中传递一个对象数组进去,里面包含了构造器所需的各个参数
3、通过Constructor实例化对象
- 调用指定的方法
- 通过Class类的getMethod(String name, Class<?>… parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的的参数类型
- 之后调用Object invoke(Object obj, Object… args) 进行调用,并向方法传递要设置的ojb对象的参数信息
- Object invoke(Object obj, Object… args)
- Object 对应原方法的返回值,若原方法没有返回值怎返回null
- 若原方法为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显示调用方法对象的setAccessible(true)方法,将可访问private的方法
- setAccessible
- Method和Field、Constructor对象都有setAccessible()方法
- setAccessible的作用是 启动和禁用访问安全检查的开关
- 参数为true表示反射的对象在使用时取消了Java语言的访问检查,关闭后可以提高反射效率,可以访问原本无法访问的私有成员
public class Demo09 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("com.phx.reflection.Users");
Users users = (Users) c1.newInstance();
System.out.println(users);
Constructor constructor = c1.getConstructor(String.class, String.class, int.class);
Users users2 = (Users) constructor.newInstance("zs","男",18);
System.out.println(users2);
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(users2,"ls");
Method getName = c1.getMethod("getName");
System.out.println(getName.invoke(users2));
Method sayHello = c1.getDeclaredMethod("sayHello", String.class);
sayHello.setAccessible(true);
sayHello.invoke(users2,"zs");
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(users,"ww");
Method getName2 = c1.getMethod("getName");
System.out.println(getName2.invoke(users));
}
}
@SuppressWarnings("all")
public class Demo10 {
public static void test01(){
Users users=new Users();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
users.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方式调用10亿次调用耗时:"+(endTime-startTime)+"ms");
}
public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Users users=new Users();
long startTime = System.currentTimeMillis();
Method getName = users.getClass().getMethod("getName");
for (int i = 0; i < 1000000000; i++) {
getName.invoke(users);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式调用10亿次调用耗时:"+(endTime-startTime)+"ms");
}
public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Users users=new Users();
long startTime = System.currentTimeMillis();
Method getName = users.getClass().getMethod("getName");
getName.setAccessible(true);
for (int i = 0; i < 1000000000; i++) {
getName.invoke(users);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式关闭安全检查调用10亿次调用耗时:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test01();
test02();
test03();
}
}