JAVA反射(三)

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章