java学习笔记之反射

1、获得Class对象(反射的源头)

三种方式:
    a、类.class
    b、对象.getClass()
    C、Class.forName(String className) (className为完整类名,包括包名)

2、获取类名、构造函数、属性、方法

a、获取类名:
    getName()  获取完整类名,包含包名
    getSimpleName() 获取类名,不包含包名
b、获取构造函数 Constructor
    getConstuctors()  获取public权限构造函数,无法获取其它权限构造函数
    getDeclaredConstructors() 获取所有权限构造函数
    getConstructor(Class... parameterTypes) 获取指定public权限构造函数
    getDeclaredConstructor(Class... parameterTypes) 获取指定任意权限构造函数
c、获取属性 Field
    getFields()  获取public权限属性,无法获取其它权限构造属性
    getDeclaredFields() 获取所有权限属性
    getField(String name) 获取指定public权限属性
    getDeclaredField(String name) 获取指定任意权限属性
d、获取方法 Method
    getMethods()  获取public权限方法,无法获取其它权限方法
    getDeclaredMethods() 获取所有权限方法
    getMethod(Class... parameterTypes) 获取指定public权限方法
    getDeclaredMethod(Class... parameterTypes) 获取指定任意权限方法

代码示例:

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

/**
 * 通过反射,获取类名、构造函数、属性、方法
 * @author ly1
 *
 */
public class GetInfo{
    public static void main(String[] args) throws Exception  {
        //获取Class对象=====================================================================================
        Student student = new Student();
        Class clazz = Student.class;
        clazz = student.getClass();
        clazz = Class.forName("Reflect.Student");

        //获取类名===========================================================================================
        String name = clazz.getName();  //完整类名,包括包名
        System.out.println("获取类名:"+name); 

        name = clazz.getSimpleName();   //类名,不含包名
        System.out.println("获取完整类名:"+name);

        //获取构造函数=======================================================================================
        //获取public权限构造函数,无法获取其它权限构造函数
        Constructor[] constructors = clazz.getConstructors(); 
        System.out.println("获取public权限构造函数,无法获取其它权限构造函数:");
        System.out.println("\t"+constructors.length);
        for (Constructor constructor : constructors) {
            System.out.println("\t"+constructor);
        }

        //获取所有权限构造函数,包括public、default、protected、private
        constructors = clazz.getDeclaredConstructors();  
        System.out.println("获取所有权限构造函数,包括public、default、protected、private:");
        System.out.println("\t"+constructors.length);
        for (Constructor constructor : constructors) {
            System.out.println("\t"+constructor);
        }

        //根据构造函数的参数类型获取指定构造函数
        Constructor constructor = clazz.getConstructor(String.class,char.class,int.class,double.class); 
        System.out.println("根据构造函数的参数类型获取指定构造函数:");
        System.out.println("\t"+constructor);

        //获取属性==========================================================================================
        //获取public权限属性,无法获取其它权限属性 
        Field[] fields = clazz.getFields();
        System.out.println("获取public权限属性,无法获取其它权限属性 :");
        System.out.println("\t"+fields.length);
        for(Field f : fields){
            System.out.println("\t"+f);
        }

        //获取所有权限的属性,包括public、default、protected、private
        fields = clazz.getDeclaredFields(); 
        System.out.println("获取所有权限的属性,包括public、default、protected、private :");
        System.out.println("\t"+fields.length);
        for(Field f : fields){
            System.out.println("\t"+f);
        }

        //根据属性名获取指定属性
        Field field = clazz.getDeclaredField("name");
        System.out.println("根据属性名获取指定属性:"); 
        System.out.println("\t"+field);

        //获取方法===========================================================================================
        //获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法
        Method[] methods = clazz.getMethods(); 
        System.out.println("获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法:"); 
        System.out.println("\t"+methods.length);
        for (Method method : methods) {
            System.out.println("\t"+method);
        }

        //获取所有权限的方法,包括public、default、protected、private
        methods = clazz.getDeclaredMethods();  
        System.out.println("获取所有权限的方法,包括public、default、protected、private:");
        System.out.println("\t"+methods.length);
        for (Method method : methods) {
            System.out.println("\t"+method);
        }

        //根据方法名和参数类型,获取指定方法
        Method method = clazz.getDeclaredMethod("setName", String.class);  
        System.out.println("根据方法名和参数类型,获取指定方法:");
        System.out.println("\t"+method);
    }
}

结果:
获取类名:Reflect.Student
获取完整类名:Student
获取public权限构造函数,无法获取其它权限构造函数:
    2
    public Reflect.Student()
    public Reflect.Student(java.lang.String,char,int,double)
获取所有权限构造函数,包括public、default、protected、private:
    2
    public Reflect.Student()
    public Reflect.Student(java.lang.String,char,int,double)
根据构造函数的参数类型获取指定构造函数:
    public Reflect.Student(java.lang.String,char,int,double)
获取public权限属性,无法获取其它权限属性 :
    1
    public double Reflect.Student.height
获取所有权限的属性,包括public、default、protected、private :
    4
    private java.lang.String Reflect.Student.name
    char Reflect.Student.sex
    protected int Reflect.Student.age
    public double Reflect.Student.height
根据属性名获取指定属性:
    private java.lang.String Reflect.Student.name
获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法:
    15
    public java.lang.String Reflect.Student.getName()
    public void Reflect.Student.setName(java.lang.String)
    public int Reflect.Student.getAge()
    public char Reflect.Student.getSex()
    public void Reflect.Student.setHeight(double)
    public double Reflect.Student.getHeight()
    public boolean java.lang.Object.equals(java.lang.Object)
    public final native java.lang.Class java.lang.Object.getClass()
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public native int java.lang.Object.hashCode()
    public java.lang.String java.lang.Object.toString()
    public final native void java.lang.Object.notifyAll()
    public final native void java.lang.Object.notify()
获取所有权限的方法,包括public、default、protected、private:
    8
    public java.lang.String Reflect.Student.getName()
    public void Reflect.Student.setName(java.lang.String)
    public int Reflect.Student.getAge()
    public char Reflect.Student.getSex()
    public void Reflect.Student.setHeight(double)
    protected void Reflect.Student.setAge(int)
    private void Reflect.Student.setSex(char)
    public double Reflect.Student.getHeight()
根据方法名和参数类型,获取指定方法:
    public void Reflect.Student.setName(java.lang.String)

3、动态操作构造函数、属性、方法

1)操作构造函数
    a、利用Class对象调用空构造:
    Class对象.newInstance()  该方法得确保该类有空构造(显示或隐式)
    b、利用Constructor.newInstance():
    Constructor对象.newInstance()  该方法可以调用任意构造方法,如果不可访问,须设置setAccessible(true)
2)操作属性
    a、操作可访问属性
        Field对象.set(Object obj,Object value)
    b、操作不可访问属性
        须先设置 Field对象setAccessible(true)
        然后 Field对象.set(Object obj,Object value)
3)操作方法
    a、操作可访问方法
        Method对象.invoke(Object obj,Object... args)
    b、操作不可访问方法
        须先设置 Method对象setAccessible(true)
        然后 Method对象.invoke(Object obj,Object... args)

代码示例:

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

/**
 * 通过反射操作类的构造函数、属性、方法
 * @author ly1
 *
 */
public class OperateInfo {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException,
                                                    SecurityException, IllegalArgumentException, InvocationTargetException,
                                                    NoSuchFieldException {
        //获取Class对象
        Class clazz = Student.class;

        //利用反射API创建对象====================================================================
        //直接调用Class对象的newInstance()方法,必须保证Student对象有空构造(显示或隐式)
        Student student = (Student) clazz.newInstance();
        System.out.println(student);

        //获取到构造函数创建对象
        Constructor<Student> constructor = clazz.getConstructor(String.class,char.class,int.class,double.class);
        student = constructor.newInstance("张三",'男',20,178.51);
        System.out.println(student);

        //利用反射API操作属性
        //操作可访问属性
        Field field = clazz.getField("height");
        field.set(student, 188.00);
        System.out.println(field.get(student));
        //操作不可访问属性,设置setAccessible(true)
        field = clazz.getDeclaredField("name");
        field.setAccessible(true);         //使反射对象该属性在使用时不对其进行安全检查
        field.set(student, "李四");
        System.out.println(field.get(student));

        //利用反射API操作方法
        //操作可访问方法
        Method method = clazz.getMethod("setName", String.class);
        method.invoke(student, "王麻子");
        System.out.println(student.getName());
        //操作不可访问方法,设置setAccessible(true)
        method = clazz.getDeclaredMethod("setSex", char.class);
        method.setAccessible(true);          //使反射对象该方法在使用时不对其进行安全检查
        method.invoke(student, '女');
        System.out.println(student.getSex());

    }
}


结果:Reflect.Student@39e2ee3f
     Reflect.Student@24348ab2
     188.0
     李四
     王麻子
     女

4、反射机制性能

使用反射机制性能降低,如果禁止安全检查,性能会有所上升,但还是比不使用反射性能低。

代码测试:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 测试反射机制的性能
 * @author ly1
 *
 */
public class ReflectPerformance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("Reflect.Student");
        Student stu = (Student) clazz.newInstance();

        test01(stu);
        test02(clazz,stu);
        test03(clazz,stu);
    }

    public static void test01(Student stu){
        long startTime = System.currentTimeMillis();
        for(int i = 0;i < 1000000000L;i++){
            stu.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("不使用反射机制运行时间为:"+(endTime - startTime) +"ms");
    }

    public static void test02(Class clazz,Student stu){
        try {
            Method method = clazz.getMethod("getName");
            long startTime = System.currentTimeMillis();
            for(int i = 0;i < 1000000000L;i++){
                method.invoke(stu, null);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("使用反射机制,进行安全检查运行时间为:"+(endTime - startTime) +"ms");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }

    public static void test03(Class clazz, Student stu){
        try {
            Method method = clazz.getMethod("getName");
            method.setAccessible(true);
            long startTime = System.currentTimeMillis();
            for(int i = 0;i < 1000000000L;i++){
                method.invoke(stu, null);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("使用反射机制,不进行安全检查运行时间为:"+(endTime - startTime) +"ms");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

结果:不使用反射机制运行时间为:332ms
     使用反射机制,进行安全检查运行时间为:1769ms
     使用反射机制,不进行安全检查运行时间为:1201ms

5、反射操作泛型

1)获取泛型参数
    Method对象.getGenericParameterTypes():Type[]
        获取具体类型:
        ParameterizedType对象.getActualTypeArguments():Type[]
2)获取泛型返回值
    Method对象.getGenericReturnType():Type
        获取具体类型:
        ParameterizedType对象.getActualTypeArguments():Type[]

代码示例:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * 反射操作泛型
 * @author ly1
 *
 */
public class ReflectGeneric {
    public static List<Integer> test(Map<String,Student> map,List<Double> list){
        return null;
    }

    public static void main(String[] args) {
        try{
            Class clazz = ReflectGeneric.class;
            Method method = clazz.getMethod("test", Map.class,List.class);

            //获取泛型参数的类型
            Type[] types = method.getGenericParameterTypes();
            for (Type type : types) {
                System.out.println("泛型参数:"+type);
                if(type instanceof ParameterizedType){
                    Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments();
                    for (Type type2 : aTypes) {
                        System.out.println("\t"+type2);
                    }
                }
            }

            //获取泛型返回值的类型
            Type type = method.getGenericReturnType();
            System.out.println("泛型返回值:"+type);
            if(type instanceof ParameterizedType){
                Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments();
                for (Type type2 : aTypes) {
                    System.out.println("\t"+type2);
                }
            }
        }
        catch(Exception e){

        }
    }
}


结果:
泛型参数:java.util.Map<java.lang.String, Reflect.Student>
    class java.lang.String
    class Reflect.Student
泛型参数:java.util.List<java.lang.Double>
    class java.lang.Double
泛型返回值:java.util.List<java.lang.Integer>
    class java.lang.Integer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值