zoukankan      html  css  js  c++  java
  • Java基础一篇过(一)反射

    一、反射是个啥

      定义 : 在运行状态中动态获取类的信息以及动态调用对象的方法,这种功能称为java语言的反射机制。

    • 对于任意一个类,都能够知道这个类的所有属性和方法。
    • 对于任意一个对象,都能够调用它的任意一个方法和属性。

    二、Class对象

      定义 : 我们在开发过程中,创建的每一个类也是对象,即类本身是java.lang.Class类的实例对象,我们称这个实例对象为类对象,也就是Class对象。

      学习反射前我们先要了解类对象有什么用:

    • Class 类的实例对象表示正在运行的 Java 应用程序中的类和接口。
    • Jvm中有很多的实例,每个类都有唯一的Class对象。 Class 类没有公共构造方法。
    • Class 对象是在加载类时由 Java 虚拟机自动构造的。也就是说我们不需要创建,JVM已经帮我们创建了。
    • Class 对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法 。

      获取Class对象有以下几种方法:

    • Class.forName()(常用)
    • Test.class
    • new Test().getClass()
    /**
     * 反射机制demo
     */
    public class Test {
        public static void main(String args[]) throws Exception {
            /*获取类对象的三种方法*/
            //1、Class.forName()(常用)
            Class class1 = Class.forName("zhbf.web.Test");
            //2、Test.class
            Class class2 = Test.class;
            //3、new Test().getClass()
            Class class3 = new Test().getClass();
    
            /*三种方式创建的类对象调用其中的方法*/
            Method method1 = class1.getMethod("printSome",String.class);
            method1.invoke(class1, "class1");
            Method method2 = class2.getMethod("printSome",String.class);
            method2.invoke(class2, "class2");
            Method method3 = class3.getMethod("printSome",String.class);
            method3.invoke(class3, "class3");
        }
    
        public static void printSome(String className) {
            System.out.println(className + "通过反射机制获取方法并调用~");
        }
    }

    运行main方法:

    三、利用反射机制创建对象

    步骤:

    /*创建对象的流程*/
    //1.获取类对象
    Class classTest = Class.forName("zhbf.web.Test");
    //2.获取构造器对象(入参为选用的构造方法的参数类型)
    Constructor con = classTest.getConstructor();
    //3 获取对象
    Test test = (Test) con.newInstance();
    • getConstructors() :所有"公有的"构造方法
    • getDeclaredConstructors() :获取所有的构造方法(包括私有、受保护、默认、公有) 
    • getConstructor(构造方法的参数类型) :  获取单个的"公有的"构造方法
    • getDeclaredConstructor(构造方法的参数类型) : 获取"某个构造方法"可以是私有的,或受保护、默认、公有;
    • newInstance() : 获取对象

    四、获取成员变量并使用

    常用方法:

    • getField(属性名) : 只能获取public的,包括从父类继承来的字段
    • getDeclaredField(属性名) :  获取本类包括public、private和proteced的字段,但是不能获取继承来的字段
    • getDeclaredFields() : 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段
    • setAccessible(布尔值): 设置变量是否可访问
    /*获取属性并修改*/
    ZhbfwebApplicationTests testClass = new ZhbfwebApplicationTests();
    //获取ZhbfwebApplicationTests类里访问权限为private的变量name
    Field field = Class.forName("zhbf.web.ZhbfwebApplicationTests").getDeclaredField("name");
    //设置变量可访问(ture)
    field.setAccessible(true);
    //上一步设置后,可对private的变量进行从新赋值
    field.set(testClass, "wlx");
    //打印从testClass对象里面获取的name变量
    System.out.println(field.get(testClass));

    五、获取成员方法并使用

    常用方法:

    • getMethod(方法名 ,入参类型)  : 获取"公有方法";(包含了父类的方法也包含Object类)
    • getDeclaredMethods(方法名 ,入参类型)  : 获取成员方法,包括私有的(不包括继承的)
    • invoke(对象,参数) : 调用方法
    //调用方法并传入参数
    Class class1 = Test.class;
    Method method = class1.getMethod("printSome", String.class);
    method.invoke(class1, "class1");

    六、反射的常见应用

      反射的常见应用场景如下:

    Spring框架的配置文件设计思想

      Spring框架的配置文件一般命名为application.properties,公用的配置一般都写在这里面,为什么要以这种方式来写入公共的信息呢?

      场景举例例如我们需要配置数据库连接信息:

    • 写在代码里,修改数据库连接地址就需要重新编译,相当麻烦
    • 写在配置文件里,利用反射机制读取,不用从新编译,只需要修改单独的配置文件内容就好。

    代码:

    /**
     * 反射机制读取文件
     */
    public class Test {
    
        public static void main(String args[]) throws Exception {
            //从application.properties中获取类名称和方法名称
            File springConfigFile = new File("E:\MyOwnGit\ZHBF\ZHBF-WEB\src\main\resources\application.properties");
            //Properties是Java语言的配置文件所使用的类,Xxx.properties为Java 语言常见的配置文件
            Properties springConfig = new Properties();
            //文件输入流读取文件内容
            springConfig.load(new FileInputStream(springConfigFile));
            String driverClass = (String) springConfig.get("spring.datasource.driver-class-name");
            String url = (String) springConfig.get("spring.datasource.url");
            String username = (String) springConfig.get("spring.datasource.username");
            String password = (String) springConfig.get("spring.datasource.password");
            System.out.println("=====输出数据库配置=====");
            System.out.printf("驱动类:%s url:%s 用户名:%s 密码:%s", driverClass, url, username, password);
        }
    
    }

    输出:

    修改配置文件后输出:

  • 相关阅读:
    HDU 4278 Faulty Odometer 8进制转10进制
    hdu 4740 The Donkey of Gui Zhou bfs
    hdu 4739 Zhuge Liang's Mines 随机化
    hdu 4738 Caocao's Bridges tarjan
    Codeforces Gym 100187M M. Heaviside Function two pointer
    codeforces Gym 100187L L. Ministry of Truth 水题
    Codeforces Gym 100187K K. Perpetuum Mobile 构造
    codeforces Gym 100187J J. Deck Shuffling dfs
    codeforces Gym 100187H H. Mysterious Photos 水题
    windows服务名称不是单个单词的如何启动?
  • 原文地址:https://www.cnblogs.com/riches/p/12069323.html
Copyright © 2011-2022 走看看