一、使用反射時,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)