java反射基础

 1 package com.demo.bean;
 2 
 3 import java.util.Date;
 4 
 5 public class User {
 6     public String name;
 7     private int age;
 8     
 9     public User() {}
10     
11     public User(String name, int age) {
12         super();
13         this.name = name;
14         this.age = age;
15     }
16     
17     public String getName() {
18         return name;
19     }
20     public void setName(String name) {
21         this.name = name;
22     }
23     public int getAge() {
24         return age;
25     }
26     public void setAge(int age) {
27         this.age = age;
28     }    
29     public String show() {
30         return "User [name=" + name + ", age=" + age + "]";
31     }
32     
33 }
用来反射的对象 User

 

1             User u = new User();2             Class clazz01 = Class.forName("com.demo.bean.User");
3             Class clazz02 = u.getClass();
4             Class clazz03 = u.class;

通过class获得类名,属性,方法,构造器对象

       Class clazz = Class.forName("com.demo.bean.User");
       // 包名+类名 Class className = clazz.getName();
// 类名 String simpleName = clazz.getSimpleName(); // 返回一个public 的属性对象 Field Field nameField = clazz.getField("name"); // 返回包含所有的public 属性数组 Field[] Field[] fields = clazz.getFields(); // 返回一个 的属性对象 Field(包括private) Field pwdField = clazz.getDeclaredField("age"); // 返回包含所有的 属性数组(包括private) Field[] declaredFields = clazz.getDeclaredFields(); // 通过方法名字和参数获得方法对象 Method method = clazz.getDeclaredMethod("getAge"); Method method02 = clazz.getDeclaredMethod("setAge",int.class); // 获得所有方法 Method[] methods = clazz.getDeclaredMethods(); // 通过参数获得构造器对象 Constructor ctr01 = clazz.getDeclaredConstructor(); Constructor ctr02 = clazz.getDeclaredConstructor(String.class,int.class); // 获得所有构造器对象 Constructor[] ctrs = clazz.getDeclaredConstructors(); // 产生无参数构造,javabean必须要有无参数构造 User use02 = (User) clazz.newInstance();

反射生成对象和调用方法

package com.demo.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.demo.bean.User;

public class Demo01 {
    
    public static void main(String[] args) throws Exception {
        
            Class clazz = User.class;
            // 无参对象
            User u1 = (User) clazz.newInstance();
            // 有参对象
            Constructor ctr = clazz.getDeclaredConstructor(String.class,int.class);
            User u2 = (User) ctr.newInstance("ouyangri",21);
            
            // 获得setName,并调用
            Method method02 = clazz.getDeclaredMethod("setName",String.class);
            method02.invoke(u2,"小红");
            // 获得getName,并调用
            Method method = clazz.getDeclaredMethod("getName");
            // 私有方法必须设置为可访问
            method.setAccessible(true);
            String name = (String) method.invoke(u2);
            
            // 获得属性
            Field f = clazz.getDeclaredField("age");
            // 私有属性必须设置为可访问
            f.setAccessible(true);
            // 设置属性值
            f.set(u2, 24);
            // 获得属性值
            int age = (int) f.get(u2);
        
    }
}

注意: 如果需要频繁的用反射访问属性或者方法,应该设置 setAccessible(true),减少安全性检查,提高效率。

package com.demo.reflect;

import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;

import com.demo.bean.User;

public class Demo01 {
    public static void main(String[] args) throws Exception {
        for(int i = 0;i < 5;i++)
        {
            test01();//普通方法调用
            test02();// 安全行检查反射方法调用
            test03();// 无安全行检查,反射方法调用
            System.out.println("#######################################");
        }
    }
    
    // 普通方法调用
    public static void test01() {
        long start = System.currentTimeMillis();
        User u = new User();
        for(int i = 0;i < 1000000000L;i++)
            u.getName();
        long end = System.currentTimeMillis();
        System.out.println("普通方法调用:执行十亿次: "+(double)(end-start)/1000);
    }
    // 安全行检查反射方法调用
    public static void test02() throws Exception{
        long start = System.currentTimeMillis();
        User u = new User();
        Method method = u.getClass().getMethod("getName");
        for(int i = 0;i < 1000000000;i++)
            method.invoke(u);
        long end = System.currentTimeMillis();
        System.out.println("安全行检查反射方法调用:执行十亿次: "+(double)(end-start)/1000);
    }
    // 无安全行检查,反射方法调用
    public static void test03() throws Exception{
        long start = System.currentTimeMillis();
        User u = new User();
        Method method = u.getClass().getMethod("getName");
        method.setAccessible(true);
        
        for(int i = 0;i < 1000000000;i++)
            method.invoke(u);
        long end = System.currentTimeMillis();
        System.out.println("无安全行检查,反射方法调用:执行十亿次: "+(double)(end-start)/1000);
    }
}
效率对比

 

Console:

普通方法调用:执行十亿次: 0.352
安全性检查反射方法调用:执行十亿次: 1.422
无安全性检查,反射方法调用:执行十亿次: 0.833
#######################################
普通方法调用:执行十亿次: 0.354
安全性检查反射方法调用:执行十亿次: 1.384
无安全性检查,反射方法调用:执行十亿次: 0.817
#######################################
普通方法调用:执行十亿次: 0.353
安全性检查反射方法调用:执行十亿次: 1.253
无安全性检查,反射方法调用:执行十亿次: 0.678
#######################################
普通方法调用:执行十亿次: 0.346
安全性检查反射方法调用:执行十亿次: 1.233
无安全性检查,反射方法调用:执行十亿次: 0.678
#######################################
普通方法调用:执行十亿次: 0.343
安全性检查反射方法调用:执行十亿次: 1.24
无安全性检查,反射方法调用:执行十亿次: 0.689
#######################################

反射操作泛型(generic)

Type  是Java编程语言中所有类型的通用超级接口。 这些包括原始类型,参数化类型,数组类型,类型变量和原始类型。

ParameterizedType  表示一个参数化类型,如Collection <String>。

GenericArrayType  表示参数化类型或类型变量的数组类型。

package com.demo.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class Demo01 {
    
    public static void main(String[] args) throws Exception {
        
        //test01();
        //test02();
        //test03();
    }
    // 获得方法参数下的参数化类型
    static void test01() throws Exception {
        Class clazz = Class.forName("com.demo.reflect.GenericTest");
        GenericTest gt = (GenericTest) clazz.newInstance();
        Method method = clazz.getMethod("test01",Map.class,LinkedList.class,String.class);
        // 获取test01方法下所有的参数化类型 参数
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        
        for(Type t:genericParameterTypes) {
            // 如果是参数化类型,就打印
            if(t instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) t;
                System.out.println("参数化类型:"+ptype.getTypeName());
                // 获取参数化类型下所有的 具体类型
                Type[] actualTypeArguments = ptype.getActualTypeArguments();
                for(Type tt:actualTypeArguments) {
                    System.out.println("\t"+tt.getTypeName());
                }
            
            }
        }
        
        
    }
    // 获得方法返回值的参数化类型
    static void test02() throws Exception {
        Class clazz = Class.forName("com.demo.reflect.GenericTest");
        GenericTest gt = (GenericTest) clazz.newInstance();
        Method method = clazz.getMethod("test01",Map.class,LinkedList.class,String.class);
        // 获取test01方法返回值下所有的参数化类型 参数
        Type t = method.getGenericReturnType();
        if(t instanceof ParameterizedType) {
            ParameterizedType ptype = (ParameterizedType) t;
            System.out.println("参数化类型:"+ptype.getTypeName());
            // 获取参数化类型下所有的 具体类型
            Type[] actualTypeArguments = ptype.getActualTypeArguments();
            for(Type tt:actualTypeArguments) {
                System.out.println("\t"+tt.getTypeName());
            }
        }
    }
    // 获得属性的参数化类型
    static void test03() throws Exception {
        Class clazz = Class.forName("com.demo.reflect.GenericTest");
        GenericTest gt = (GenericTest) clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();
        
        for(Field f:fields) {
            f.setAccessible(true);
            if(f.getGenericType() instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) f.getGenericType();
                System.out.println(ptype.getTypeName());
                // 获取参数化类型下所有的 具体类型
                Type[] actualTypeArguments = ptype.getActualTypeArguments();
                for(Type tt:actualTypeArguments) {
                    System.out.println("\t"+tt.getTypeName());
                }
            }
        }
    }
    
    
}


class GenericTest{
    private HashMap<String,Integer> map;
    private LinkedList<Double> list;
    GenericTest(){};
    public Map<String,Integer> test01(Map<String,Integer> map,LinkedList<Double> list,String str) {
        return null;
    };
}

 反射操作注解

 

package com.demo.reflect;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

@SuppressWarnings("all")
public class Demo03 {
    public static void main(String[] args) throws Exception{
        
        Class clazz = Class.forName("com.demo.reflect.User");
        User u = (User) clazz.newInstance();
        System.out.println("############## 获得类上所有的注解##############");
        // 获得类上所有的注解
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation an : annotations) {
            System.out.println(an);
        }
        System.out.println("############## 获得类上指定名称的注解##############");
        // 获得类上指定名称的注解
        Myannotation myat = (Myannotation) clazz.getAnnotation(Myannotation.class);
        String tableName = myat.value();
        System.out.println("tableName: "+tableName);
        
        
        // 获得指定名称字段的注解
        System.out.println("##############获得指定名称字段的注解###############");
        Field field = clazz.getDeclaredField("username");
        Myannotation myat02 = field.getAnnotation(Myannotation.class);
        System.out.println("columnName: "+myat02.columnName());
        System.out.println("type: "+myat02.type());
        System.out.println("length: "+myat02.length());
        
        // 获得字段下所有的注解
        System.out.println("##############获得字段下所有的注解###############");
        Field[] fields = clazz.getDeclaredFields();
        for(Field f : fields) {
            Myannotation myat03 = f.getAnnotation(Myannotation.class);
            System.out.println("columnName: "+myat03.columnName());
            System.out.println("type: "+myat03.type());
            System.out.println("length: "+myat03.length());
        }

        
        
    }
}

// 元注解@Target,描述注解可以作用的范围
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//    元注解@@Retention,描述注解保留时期
@Retention(RetentionPolicy.RUNTIME)
@interface Myannotation {
    /*
         格式: 
            类型   属性名() [default 属性值]
     */
    String columnName() default "";
    
    String type() default "";
    
    // 带有默认值可以不进行赋值操作
    int length() default -1;
    
    /*
     如果属性是 value 默认不通过属性名赋值  
    ex: 
        Myannotation("xxxx") == Myannotation(value="xxxx")
     */
    String value() default "";
}


@Myannotation("user")
class User{
    @Myannotation(columnName="username",type="varchar",length=20)
    private String username;
    @Myannotation(columnName="pwd",type="varchar",length=20)
    private String pwd;
    
    public User() {
        super();
    }

    public User(String username, String pwd) {
        super();
        this.username = username;
        this.pwd = pwd;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    
}

 

posted @ 2019-04-24 22:38  ouyangyangyang  阅读(143)  评论(0编辑  收藏  举报