zoukankan      html  css  js  c++  java
  • 反射

    前言

    反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件

    概述

    JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道这个类的所有信息,比如:成员变量、方法、构造方法、包等信息;要想用反射机制,首先要获取到

    该类的字节码文件对象Class,然后用Class类中的方法把各种成分映射成Java对象,关于.class文件,在我们new对象的时候,本地IDE自动编译,然后jvm会自动的从硬盘

    读取到.class文件,并创建一个该类的Class文件,但是,如果我们new了多个该类的实例,内存中只会有一份该类的字节码文件。

    API

    Class 类与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了 Field、Method、Constructor 类 (每个类都实现了 Member 接口)该接口反映单个成员

    (字段或方法)或构造方法的标识信息,正因为实现了该接口,因此可以反射相关变量、方法信息,这些类型的对象时由 JVM 在运行时创建的,用以表示未知类里对应的成员

    反射

    获取字节码

    在 Java 中可以通过三种方法获取类的字节码 (Class) 对象,如下:

    package com.oxygen.bean;
    
    public class ReflectTest {
        public static void main(String[] args) throws ClassNotFoundException {
            Student student = new Student();
            Class<?> clazz1 = student.getClass(); //方式1
            Class<?> clazz2 = Student.class; //方式2
            Class clazz3 = Class.forName("com.oxygen.student");//方式3
        }
    }
    View Code

    获取类信息

    Student类如下

    package com.oxygen.bean;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    public class Student {
        private String name;
        private Integer age;
        private Car car;
    
        public void init() {
            System.out.println("init...");
        }
    
        public void destroy() {
            System.out.println("destroy...");
        }
    
        public Student() { // 无参构造
        }
    
        public Student(String name, Integer age, Car car) {
            super();
            this.name = name;
            this.age = age;
            this.car = car;
        }
    
        private Student(String name) {
            this.name = name;
        }
     
        public void show1(String s) {
            System.out.println("调用了:公有的,String参数的show1(): name = " + s);
        }
    
        protected void show2() {
            System.out.println("调用了:受保护的,无参的show2()");
        }
    
        void show3() {
            System.out.println("调用了:默认的,无参的show3()");
        }
    
        private String show4(int age) {
            System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
            return "oxygen";
        }
    }
    View Code

    1. 通过构造函数对象Constructor创建对应类的实例

    package com.oxygen.bean;
    
    import java.lang.reflect.Constructor;
    
    public class ReflectTest {
        public static void main(String[] args) throws Exception {
            Student student = new Student(); //Student的带参构造函数依赖另外一个类Car
            Class<?> clazz1 = student.getClass(); //方式1
            func1(clazz1); //通过无参构造函数反射Student实例
            func2(clazz1);//通过有参构造函数反射Student实例
            func3(clazz1);//获取所有的构造函数反射Student实例
            func4(clazz1); // 反射私有构造函数
        }
    
        private static void func4(Class<?> clazz1) throws Exception {
            Constructor<?> declaredConstructor = clazz1.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);//设置为可以访问
            System.out.println(declaredConstructor.newInstance("zhangsan"));
        }
    
        private static void func3(Class<?> clazz1) throws Exception {
            Constructor<?>[] constructors = clazz1.getDeclaredConstructors();
            for (Constructor<?> constructor : constructors) {
                System.out.println("func3: " + constructor);
            }
        }
    
        /**
         * 因为Student的带参构造函数依赖另外一个类Car,因为必须保证JVM能获取到Car的字节码
         * @param clazz1
         * @throws Exception
         */
        public static void func2(Class<?> clazz1) throws Exception {
            Car car = new Car();//保证
            Constructor<?> constructor = clazz1.getConstructor(String.class, Integer.class, Car.class);
            Student student = (Student) constructor.newInstance("张三", 18, new Car());
            System.out.println(student);
        }
    
        public static void func1(Class<?> clazz1) throws Exception {
            Constructor<?> constructor = clazz1.getConstructor();
            Student student = (Student) constructor.newInstance();
            System.out.println(student);
        }
    }
    View Code

    2. 获取成员方法

    package com.oxygen.bean;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    public class ReflectTest {
        public static void main(String[] args) throws Exception {
            Student student = new Student();
            Class<?> clazz1 = student.getClass();
            m1(clazz1);
            m2(clazz1);
            m3(clazz1);
            m4(clazz1);
        }
    
        /**
         * 获取所有的方法,包括私有的,不包括继承Object类的9个方法
         * @param clazz1
         */
        public static void m4(Class<?> clazz1) {
            Method[] declaredMethods = clazz1.getDeclaredMethods();
        }
    
        /**
         * 获取所有的”公有“方法,包括继承Object类的9个方法
         * @param clazz1
         */
        public static void m3(Class<?> clazz1) {
            Method[] methods = clazz1.getMethods();
        }
    
        /**
         * 获取私有的show4()方法
         * @param clazz1
         * @throws Exception
         */
        public static void m2(Class<?> clazz1) throws Exception {
            Method method;
            method = clazz1.getDeclaredMethod("show4", int.class);
            Student stu = func1(clazz1); // 实例化一个Student对象
            method.setAccessible(true);
            method.invoke(stu, 20);//反射私有方法show4(),第一个参数是实例,第二个参数是被反射方法的参数
        }
    
        /**
         * 获取公有的show1()方法
         * @param clazz1
         * @throws Exception
         */
        public static void m1(Class<?> clazz1) throws Exception {
            Method method = clazz1.getMethod("show1", String.class); //第一个参数是方法名称,第二个参数是形参类型
            Student stu = func1(clazz1); // 实例化一个Student对象
            method.invoke(stu, "lisi"); //反射公有方法show1(),第一个参数是实例,第二个参数是被反射方法的参数
        }
    
        public static Student func1(Class<?> clazz1) throws Exception {
            Constructor<?> constructor = clazz1.getConstructor();
            Student student = (Student) constructor.newInstance();
            return student;
        }
    }
    View Code
  • 相关阅读:
    HBase 高性能加入数据
    Please do not register multiple Pages in undefined.js 小程序报错的几种解决方案
    小程序跳转时传多个参数及获取
    vue项目 调用百度地图 BMap is not defined
    vue生命周期小笔记
    解决小程序背景图片在真机上不能查看的问题
    vue项目 菜单侧边栏随着右侧内容盒子的高度实时变化
    vue项目 一行js代码搞定点击图片放大缩小
    微信小程序进行地图导航使用地图功能
    小程序报错Do not have xx handler in current page的解决方法
  • 原文地址:https://www.cnblogs.com/oxygenG/p/9789946.html
Copyright © 2011-2022 走看看