java之反射机制(reflection)

这篇文章讲述的是java中的反射机制,如有错误或不当之处,还望各位大神批评指正。

什么是反射机制?

  • 当程序运行时可以加载一个只有名称的类,对于一个已经加载的类都可以知道这个类的所有属性和方法,对于一个已经加载的对象,都可以调用这个对象的任意一个方法和任意属性。
  • 是指可以运行时加载、探知、使用编译期间完全未知的类。

通过Class加载类

  • java.Lang.Class用于表示一个运行时类,方式如下:

    1. 通过Class.forName获取
    2. 通过XXX.class获取
    3. 通过路径.class获取
  • 例:

//加载一个运行时类
        //方式一:通过类的全路径获取
        Class<Student> clazz = (Class<Student>) Class.forName("com.cn.cmc.reflection.Student") ;
        System.out.println(clazz);

        //方式二:通过类.class获取
        Class<Student> clazz2 = Student.class ;
        System.out.println(clazz2);

        //方式三://通过类路径.class获取
        Class<Student> clazz3 = com.cn.cmc.reflection.Student.class ;
        System.out.println(clazz3);

注:运行时类只能加载一次

操作Class类

  • 通过Class加载类之后可以对类进行动态操作,主要操作有:
    1. 动态获取类的信息(属性、构造器、方法)
    2. 动态构造对象
    3. 调用类和对象的任意的方法和构造器
    4. 动态调用和处理属性
    5. 获取泛型信息
    6. 处理注解

获取类的信息(名字、属性、方法、构造器)

获取名字

/*名字*/
//获取类的全类名
System.out.println(clazz.getName());
//获取类名
System.out.println(clazz.getSimpleName());

获取属性

/*属性*/
//获取某个public的属性(非共有的不访问)
System.out.println(clazz.getField("name"));
//获取某个属性(访问非公有)
System.out.println(clazz.getDeclaredField("name"));
//获取所有public属性(非公有不访问)
Field []f = clazz.getFields() ;
for(Field temp : f){
    System.out.println(temp);
}
//获取所有属性(访问非公有)
Field []f2 = clazz.getDeclaredFields() ;
for(Field temp : f2){
    System.out.println(temp);
}

获取方法

/*获取方法*/
//通过名称和参数类型获取方法(不包括私有方法)
Method m1 = clazz.getMethod("show", null) ;
//通过名称和参数类型获取方法(包括私有方法)
Method m2 = clazz.getDeclaredMethod("show", null) ;
//获取所有方法(不包括私有且包括所有父类方法)
Method [] methods1 = clazz.getMethods() ;
for(Method m : methods1){
    System.out.println(m);
}
//获取所有方法(包括私有且不包括父类方法)
Method [] methods2 = clazz.getDeclaredMethods() ;
for(Method m : methods2){
    System.out.println(m);
}

获取构造器

/*获取构造器*/
//获取公有构造器
Constructor c1 =  clazz.getConstructor(Integer.class, String.class, char.class, int.class) ;
System.out.println(c1);
//获取所有公有构造器
Constructor []cs1 = clazz.getConstructors() ;
for(Constructor c : cs1){
    System.out.println(c);
}
//获取构造器(包括私有)
Constructor c2 =  clazz.getDeclaredConstructor(Integer.class, String.class, char.class, int.class) ;
System.out.println(c2);
//获取所有构造器(包括私有)
Constructor []cs2 = clazz.getDeclaredConstructors() ;
for(Constructor c : cs2){
    System.out.println(c);
}

新建对象

/*新建对象*/
//通过无参构造器
Student s = clazz.newInstance() ;
System.out.println(s);
//通过制定构造器
Constructor<Student> constructor = clazz.getConstructor(Integer.class,String.class,char.class,int.class) ;
Student s2 = constructor.newInstance(100001,"叶清逸",'M',25) ;
System.out.println(s2);

调用任意对象的方法

//调用普通方法
Method m = clazz.getMethod("setName", String.class) ;
m.invoke(s, "叶清逸"); 
System.out.println(s);

调用和处理属性

//操作属性
Field f = clazz.getDeclaredField("name") ;
f.setAccessible(true);//跳过private的安全检查
f.set(s, "叶清逸");
System.out.println(f.get(s));

注:若没有f.setAccessible(true);则不可访问私有属性

反射的性能问题

  • 若使用反射机制则会带来性能的问题,执行速度比较慢,这时需要将setAccessible的值设置为true。

  • 例:

package com.cn.cmc.reflection;

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

public class test {
    /**
     * 反射机制
     */
    public static void main(String[] args) throws Exception{
        //加载一个运行时类

        test1() ;
        test2() ;
        test3() ;
    }
    public static void test1(){
        Student s = new Student() ;
        Long start = System.currentTimeMillis(); 
        for(int i=0 ; i<1000000000L ; i++){
            s.getName() ;
        }
        Long end = System.currentTimeMillis(); 
        System.out.println("普通调用耗时:"+(end-start));
    }
    public static void test2() throws Exception{
        Class<Student> clazz = Student.class ;
        Method m = clazz.getDeclaredMethod("getName") ;
        Student s = clazz.newInstance() ;
        Long start = System.currentTimeMillis(); 
        for(int i=0 ; i<1000000000L ; i++){
            m.invoke(s);
        }
        Long end = System.currentTimeMillis(); 
        System.out.println("反射调用,使用安全检查耗时:"+(end-start));
    }
    public static void test3()throws Exception{
        Class<Student> clazz = Student.class ;
        Method m = clazz.getDeclaredMethod("getName") ;
        Student s = clazz.newInstance() ;
        m.setAccessible(true);
        Long start = System.currentTimeMillis(); 
        for(int i=0 ; i<1000000000L ; i++){
            m.invoke(s);
        }
        Long end = System.currentTimeMillis(); 
        System.out.println("反射调用,跳过安全检查耗时:"+(end-start));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值