Java反射机制介绍

 更新时间:2022年08月27日 09:33:52   作者:niuyongzhi  
Java的反射机制是在运行状态中,对于任何一个类,都可以知道这个类的所有属性和方法,对于任何一个对象,都可以调用它所有的方法和属性,修改部分类型信息,这种动态获取信息以及动态调用对象方法的功能称为Java的反射机制

1.通过反射,我们可以构建实例,得到成员变量的值,得到方法并调用。

还可以获得定义在成员变量、方法、方法参数上的注解。

接下来看代码实现,然后讲原理。

1)构建无参实例:通过反射调用无参构造函数

        //1.通过全类名加载字节码对象
        Class clazz = Class.forName("com.example.lib.Person");
        //2.通过类的字节码拿到定义的构造函数
        Constructor constructor = clazz.getConstructor();
        //3.通过构造方法创建对象
        Object obj = constructor.newInstance();

2)构建有参数实例:

        //1.通过全类名加载字节码对象
        Class clazz = Class.forName("com.example.lib.Person");
        //2.通过类的字节码拿到定义的构造函数
        Constructor constructor = clazz.getConstructor(int.class,String.class);
        //3.通过构造方法创建对象
        Object obj = constructor.newInstance(20,"xiaohua");

3)通过反射获取成员变量的值。

        //4.通过属性名获取属性
        Field field = clazz.getDeclaredField("age");
        field.setAccessible(true);
        //5.调用get方法拿到对象obj属性age的值
        Integer age = (Integer) field.get(obj);

4)通过反射调用对象的方法。

        //4.通过方法名和参数类型,拿到方法
        method = clazz.getMethod("setAge", int.class);
        //5.调用方法 obj是哪个对象身上的方法。
        method.invoke(obj, 21);
        method =  clazz.getMethod("getAge");
        method.invoke(obj);

5).通过反射获取静态变量的值。

       //1.通过全类名加载字节码对象
        Class clazz = Class.forName("com.example.lib.Person");
        //2.获取静态属性ID
        Field  field = clazz.getField("ID");
        field.setAccessible(true);
        //3.拿到静态属性ID的值。
        // 因为静态变量存在方法区,在对象创建之前,就已经加装到了内存
        //所以,没有对象,也可以获取变量的值,这里传null也是可以的。
        int id = (int) field.get(null);

2.通过反射获取定义的注解的值

1)获取成员变量的注解以及值。

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    int value();
}
public class MainActivity {
    @BindView(10000)
    TextView textView;
}
        //10通过反射拿到定义在属性上的注解
        Class  clazz = MainActivity.class;
        Field textView = clazz.getDeclaredField("textView");
        BindView bindView = textView.getAnnotation(BindView.class);
        int txtId = bindView.value();

3)通过反射获取定义在方法和方法参数上的注解以及值

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Post {
    String value() default "";
}
public interface NetWorkInterface {
    @Post("http://www.baidu.com")
    Call getPerson(@Queue("name") String name, @Queue("200") int price);
}
      //11通过反射拿到方法上定义的注解
        clazz = NetWorkInterface.class;
        Method method = clazz.getMethod("getPerson", String.class, int.class);
        //获取Post注解
        Post post = method.getAnnotation(Post.class);
        //获取值
        String url = post.value();
         //12通过反射拿到参数上的注解
        //为是个二维数组,因为方法参数会有多个,一个参数有可能定义多个注解
        Annotation[][] annotations = method.getParameterAnnotations();
        for (Annotation[] ans : annotations) {
            for (Annotation an : ans) {
                if (an instanceof Queue) {
                    Queue queue = (Queue) an;
                    String value = queue.value();
                }
            }
        }

4)获取方法的参数和返回值类型。

        //13.拿到方法参数的类型。
        Type[] types = method.getGenericParameterTypes();
        for (Type type : types) {
            System.out.println(type.toString());
        }
        //14.获取方法返回值类型
        Type type = method.getGenericReturnType();

3总结:通过反射,可以拿到对象身上的成员变量的值、调用方法,获取定义在成员变量、方法和 方法参数上的注解。Retrofit 就用到了注解加反射技术,和动态代理(这个技术稍后分享)

4.通过反射,可以做到以上事情。反射的原理是啥?

1)我们写的源代码是.java文件,通过javac编译后成为.class文件,即字节码文件。

2)程序执行时,JVM会类加载字节码文件到内存,严格意义上说是加载到方法区,并转换成

java.lang.Class对象。万事万物皆对象,Class被称为类对象,描述类在元数据空间的数据结构,包含类中定义的属性、方法、构造方法、注解、接口等信息。

所有反射的第一步是拿到类对象Class对象。拿到了Class对象,也就拿到了类中定义的一切。

Class clazz = Class.forName("com.example.lib.Person");

这行代码就是通过类加载器把Person类加载到内存,并得到对应的Class 对象。

到此这篇关于Java反射机制介绍的文章就介绍到这了,更多相关Java反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 你真的理解Java中的ArrayList吗

    你真的理解Java中的ArrayList吗

    这篇文章主要给大家介绍了关于Java中ArrayList的相关资料,ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,需要的朋友可以参考下
    2021-08-08
  • Caused by: java.lang.NumberFormatException: For input string: “port“(问题解决)

    Caused by: java.lang.NumberFormatException: For input s

    这篇文章主要介绍了Caused by: java.lang.NumberFormatException: For input string: “port“,本文给大家分享完美解决方法,需要的朋友可以参考下
    2023-01-01
  • Java的引用类型常用的四种方法

    Java的引用类型常用的四种方法

    这篇文章主要介绍了Java的引用类型常用的几种方法,Java为引用类型专门定义了一个类Reference,它是引用对象的抽象基类,相关内容需要的小伙伴可以参考一下
    2022-06-06
  • Hibernate的Annotation版Hello world实例

    Hibernate的Annotation版Hello world实例

    这篇文章主要介绍了Hibernate的Annotation版Hello world实现方法,详细分析了Annotation的具体使用步骤与Hello world实现方法,需要的朋友可以参考下
    2016-03-03
  • java将指定目录下文件复制到目标文件夹的几种小方法

    java将指定目录下文件复制到目标文件夹的几种小方法

    在Java中有多种方法可以实现文件的复制,这篇文章主要给大家介绍了关于java将指定目录下文件复制到目标文件夹的几种小方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Java MyBatis是如何执行一条SQL语句的

    Java MyBatis是如何执行一条SQL语句的

    这篇文章主要介绍了Java MyBatis是如何执行一条SQL语句的,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • Java发送https请求并跳过ssl证书验证方法

    Java发送https请求并跳过ssl证书验证方法

    最近在负责一个对接第三方服务的事情,在对接期间因为第三方服务为https的请求,这篇文章主要给大家介绍了关于Java发送https请求并跳过ssl证书验证的相关资料,需要的朋友可以参考下
    2023-11-11
  • 猜数游戏java实现代码

    猜数游戏java实现代码

    这篇文章主要为大家详细介绍了java实现猜数游戏代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • java多线程-读写锁原理

    java多线程-读写锁原理

    本文主要介绍java多线程的知识,这里整理了相关资料及简单示例代码,有兴趣的小伙伴可以参考下
    2016-09-09
  • SpringBoot可以同时处理多少请求流程分析

    SpringBoot可以同时处理多少请求流程分析

    SpringBoot默认的内嵌容器是Tomcat,也就是我们的程序实际上是运行在Tomcat里的,所以与其说SpringBoot可以处理多少请求,到不如说Tomcat可以处理多少请求,这篇文章主要介绍了SpringBoot可以同时处理多少请求,需要的朋友可以参考下
    2023-02-02

最新评论