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
  • 相关阅读:
    线程应用:(九)阻塞队列的应用
    线程应用:(八)Semaphere信号灯、CyclicBarrier汇合、CountDownLatch计数器、Exchanger
    线程应用:(七)Lock & Condition同步通信
    线程应用:(六)线程池、Callable与Future
    线程应用:(五)传统线程使用实例
    记一次linux安装mysql
    Pycharm断点调试入门
    django admin后台插件:django-suit入门
    在django中使用django_debug_toolbar
    pyquery详细用法
  • 原文地址:https://www.cnblogs.com/oxygenG/p/9789946.html
Copyright © 2011-2022 走看看