一、使用反射时,setAccessible为true、false的性能差异
网上说直接new对象调用与采用反射调用,耗时差异大约30倍;setAccessible关闭与开启,耗时差异大约4倍。
可能是我测试机硬件配置足够的高的问题,setAccessible关闭与开启后,差异并不明显,大约有100ms的延迟。
测试结果:
普通方法调用,执行10亿次,耗时:697ms
反射动态调用,执行10亿次,耗时:1729ms
反射动态调用,跳过安全检查,执行10亿次,耗时:1664ms
测试源码:
package cn.foxsand.day03;
import cn.foxsand.day02.UserBean;
import java.lang.reflect.Method;
/**
* 测试使用反射时,setAccessible为true、false的性能差异
*/
public class Demo01 {
public static void test01(){
UserBean u = new UserBean();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
u.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用,执行10亿次,耗时:" + (endTime - startTime) + "ms");
}
public static void test02(){
String path = "cn.foxsand.day02.UserBean";
try {
UserBean u = new UserBean();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getName" , null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u , null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态调用,执行10亿次,耗时:" + (endTime - startTime) + "ms");
}catch (Exception e1){
e1.printStackTrace();
}
}
public static void test03(){
String path = "cn.foxsand.day02.UserBean";
try {
UserBean u = new UserBean();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getName" , null);
m.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000L; i++) {
m.invoke(u , null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射动态调用,跳过安全检查,执行10亿次,耗时:" + (endTime - startTime) + "ms");
}catch (Exception e1){
e1.printStackTrace();
}
}
public static void main(String[] args) {
test01();
test02();
test03();
}
}
二、使用反射操作注解
2.1 测试相关类
package cn.foxsand.day01.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyTable01 {
String value();
}
package cn.foxsand.day01.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyFileld {
String columnName();
String type();
int length();
}
package cn.foxsand.day01;
import cn.foxsand.day01.annotation.MyFileld;
import cn.foxsand.day01.annotation.MyTable01;
@MyTable01(value = "tb_student")
public class Student {
@MyFileld(columnName = "id" , type = "int" , length = 10)
private int id;
@MyFileld(columnName = "studentName" , type = "varchar" , length = 10)
private String studentName;
@MyFileld(columnName = "age" , type = "int" , length = 10)
private int age;
public Student() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2.2 测试通过反射来操作注解信息
package cn.foxsand.day03;
import cn.foxsand.day01.Student;
import cn.foxsand.day01.annotation.MyFileld;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* 使用反射读取注解
*/
public class Demo03 {
public static void main(String[] args) {
try {
Class<Student> clazz = (Class<Student>) Class.forName("cn.foxsand.day01.Student");
//获取类的所有有效注解
Annotation[] annotations = clazz.getAnnotations();
for (Annotation a1:annotations
) {
System.out.println(a1);
}
// 获取类中相应属性的有效注解
Field f1 = clazz.getDeclaredField("studentName");
MyFileld myFileld = f1.getAnnotation(MyFileld.class);
System.out.println(myFileld);
}catch (Exception e1){
e1.printStackTrace();
}
}
}
测试结果:
@cn.foxsand.day01.annotation.MyTable01(value=tb_student)
@cn.foxsand.day01.annotation.MyFileld(columnName=studentName, type=varchar, length=10)