zoukankan      html  css  js  c++  java
  • Java反射

    一,反射是什么(反射是框架设计的灵魂)

    1,JAVA反射机制是在运行状态中

    对于任意一个类,都能够知道这个类的所有属性和方法;

    对于任意一个对象,都能够调用它的任意一个方法和属性;

    这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    2,反射提供的功能:

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判断任意一个类所具有的成员变量和方法
    • 在运行时调用任意一个对象的方法

    (要想解剖一个类,必须先要获取到该类的字节码文件对象(class)。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.)

    3,关于class对象和这个class类

    • Class对象的由来是将class文件读入内存,并为之创建一个Class对象

    4,class类 :代表一个类,是Java反射机制的起源和入口

    • 用于获取与类相关的各种信息, 提供了获取类信息的相关方法
    • Class类继承自Object类

    • Class类是所有类的共同的图纸

    • 每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。

    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。
    Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

    没有公共的构造方法,方法共有64个太多了。下面用到哪个就详解哪个吧

    5,反射的使用场景

    •     Java编码时知道类和对象的具体信息,此时直接对类和对象进行操作即可,无需反射
    •     如果编码时不知道类或者对象的具体信息,此时应该使用反射来实现

                比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息
                在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息

    二,获取反射入口(class对象)的三种方法

    要想操作反射,必须先拿到反射的入口

    1,通过通过Class.forName("全类名")

    try {
                Class<?> perClazz = Class.forName("reflect_fanshe.Person");
                System.out.println(perClazz);
            } catch (ClassNotFoundException e) {
                
                e.printStackTrace();

    2,类名.class

    Class<?> perClazz2 = Person.class;

    3,对象.getClass()

    Person person = new Person();
    Class<?> perClazz3 = person.getClass();

    三,根据反射入口对象(class)获取类的各种信息

    可以用一个类的反射入口class对象获取类的所有信息

    • 例1:perClazz.getMethods()  获取此类的所有public方法(父类的,实现接口的,自己的)
    Class<?> perClazz = null;
            try {
                perClazz = Class.forName("reflect_fanshe.Person");
            } catch (ClassNotFoundException e) {
                
                e.printStackTrace();
            }
            Method[] methods = perClazz.getMethods();
                    //遍历所有方法
            for (Method method : methods) {
                System.out.println(method);
            }
        }
    • 例2:获取所有的构造方法

    • 例3: 获取父类

    •  例4:获取当前类(只有本类的)的所有方法和属性,包括私有的

     

    •  重要:可以获取当前类的对象,并通过对象调用类的方法

    四,通过反射获取对象的实例,并操作对象

    1,class.newInstance() ,并强转类型,然后就可以操作对象了,主要是调用方法。

    2,操作属性,可以操作类里面的public属性和private属性

    如果属性是private,正常情况下是不允许外界操作属性值,这里可以用Field类的setAccessible(true)方法,暂时打开操作的权限

    调用方法也一样,可以调用私有的方法,null是因为这个方法没有参数

    五,在 程序执行中,动态的决定调用的类,以及方法

    在本例中,程序执行之前,程序根本不知道具体的类和方法名是什么,需要执行时解析properties文件,但是反射就可以办到。

    配置文件:

     

    反射机制:

    Java内置9大的Class实例

    对于对象来说,可以直接使用对象.getClass()或者Class.forName(className); 类名.class都可以获取Class实例.


    但是我们的基本数据类型,就没有类的权限定名,也没有getClass方法.
    问题:那么如何使用Class类来表示基本数据类型的Class实例?
    byte,short,int,long,char,float,double,boolean ,void关键字
    上述8种类型和void关键字,都有class属性.
    表示int的Class对象:  Class clz = int.class;
    表示boolean的Class对象:  boolean.class;
    void:  Class clz = void.class;


    所有的数据类型都有class属性,表示都是Class对象.


    思考:
    int的包装类是Integer
    Integer.class     ==?==         int.class
    结果是false,说明是两份字节码.


    Integer 和int是同一种数据类型吗? 不是


    但是在八大基本数据类型的包装类中都有一个常量:TYPE
    TYPE表示的是该包装类对应的基本数据类型的Class实例.
    如:Integer.TYPE----->int.class
       Integer.TYPE==int.class;//YES
       Integer.TYPE == Integer.class;//ERROR

    数组的Class实例

    :String[] sArr1 = {"A","C"};
    String[] sArr2 = {};
    String[][] sArr = {};

    int[] sArr = {};

    表示数组的Class实例:
       String[] sArr1 = {"A","C"};
       Class clz = String[].class;//此时clz表示就是一个String类型的一位数组类型

       所有具有相同元素类型和维数的数组才共享同一份字节码(Class对象);
       注意:和数组中的元素没有一点关系.

    关于setAccessible的官方说明:

    https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html

    Java反射机制提供的setAccessible()方法可以取消Java的权限控制检查。

    使用场景

    • 在编译时无法知道该对象或类可能属于哪些类,程序在运行时获取对象和类的信息

    作用

    • 通过反射可以使程序代码访问装载到 JVM 中的类的内部信息,获取已装载类的属性信息、方法信息

    优点

    • 提高了 Java 程序的灵活性和扩展性,降低耦合性,提高自适应能力。
    • 允许程序创建和控制任何类的对象,无需提前硬编码目标类
    • 应用很广,测试工具、框架都用到了反射

    缺点

    • 性能问题:反射是一种解释操作,远慢于直接代码。因此反射机制主要用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用
    • 模糊程序内部逻辑:反射绕过了源代码,无法再源代码中看到程序的逻辑,会带来维护问题
    • 增大了复杂性:反射代码比同等功能的直接代码更复杂

    【Java面试题与答案】整理推荐

  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/baldprogrammer/p/13773323.html
Copyright © 2011-2022 走看看