zoukankan      html  css  js  c++  java
  • Java反射:Web学习的灵魂

    反射:Web学习的灵魂

    我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 —— Class类对象阶段 —— Runtime运行时阶段 而我们知道,Java中一个类在源代码阶段,是存储在硬盘中的,而编译后,就已经被加载到内存中区,那么有没有一种方法可以在这种情况下,获取或者修改它的方法或者属性呢?这就是我们今天所讲的Java反射机制

    (一) 概述以及好处

    (1) 概述

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。——百度百科

    我们将类分为三部分,成员变量,构造方法,成员方法,代码编译后,变成了字节码文件(.class文件)而万物皆对象,所以在字节码文件中,又将这三部分分别整合成对象,所以我们得出结论:

    反射:将类的各个组成部分封装成对象,并通过这个Class类型的对象,去使用该文件中的成员变量,构造方法,成员方法

    (2) 好处

    1. 可以在程序“运行时”,对 .class文件进行操作,并且由此获取以及操作 类中的各个部分
    2. 可以解耦,提高程序的扩展性
    3. 增加程序的灵活性 (最后案例中体现)

    (二) 获取Class对象的方式

    (1)将字节码文件加载进内存,返回Class对象
    多用于配置文件,将类名定义在配置文件中。读取文件,加载类

    Class.forName("全类名")
    

    (2)多用于参数的传递

    类名.class
    

    (3)getClass()方法在Object类中定义着
    多用于对象的获取字节码的方式

    对象.getClass():
    

    三种方式的代码实现

    package cn.ideal.reflect;
    
    import cn.ideal.domain.Student;
    
    public class ReflectDemo1 {
        public static void main(String[] args) throws Exception {
            //1.Class.forName("全类名")
            Class cls1 = Class.forName("cn.ideal.domain.Student");
            System.out.println(cls1);
            //2.类名.class
            Class cls2 = Student.class;
            System.out.println(cls2);
            //3.对象.getClass()
            Student p = new Student();
            Class cls3 = p.getClass();
            System.out.println(cls3);
    
            //用 == 比较
            System.out.println(cls1 == cls2);//true
            System.out.println(cls2 == cls3);//true
        }
    }
    
    //运行结果
    class cn.ideal.domain.Student
    class cn.ideal.domain.Student
    class cn.ideal.domain.Student
    true
    true
    

    通过上面的案例我们可以得出:

    同一个字节码文件(*.class)在一次程序运行过程中,只加载一次,不论通过哪一种方式获取的Class对象都是同一个

    (三) Class对象功能

    (1) 获取功能:

    获取成员变量们
    //获取所有public修饰的成员变量
    Field[] getFields()
    //获取指定名称的public修饰的成员变量
    Field getField(String name)   
    
    //获取所有的成员变量,不考虑修饰符
    Field[] getDeclaredFields()  
    Field getDeclaredField(String name)  
    
    获取构造方法们
    Constructor<?>[] getConstructors()  
    Constructor<T> getConstructor(类<?>... parameterTypes)  
    
    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  
    Constructor<?>[] getDeclaredConstructors()  
    

    获取成员方法们

    Method[] getMethods()  
    Method getMethod(String name, 类<?>... parameterTypes)  
    
    Method[] getDeclaredMethods()  
    Method getDeclaredMethod(String name, 类<?>... parameterTypes)  
    

    获取全类名

    String getName()
    

    Field:成员变量

    操作:
    //设置值
    void set(Object obj, Object value)  
    //获取值
    get(Object obj)    
    //忽略访问权限修饰符的安全检查
    setAccessible(true):暴力反射
    

    Constructor:构造方法

    创建对象:
    T newInstance(Object... initargs)  
    
    如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
    

    Method:方法对象

    //执行方法
    Object invoke(Object obj, Object... args)  
    
    //获取方法名称
    String getName:获取方法名
    

    我们来具体使用一下上面的一些方法

    package cn.ideal.reflect;
    
    import cn.ideal.domain.Student;
    import java.lang.reflect.Field;
    
    public class ReflectDemo2 {
    
        public static void main(String[] args) throws Exception {
            //获取Student的Class对象
            Class studentClass = Student.class;
    
            /*
                1. 获取成员变量们
                    * Field[] getFields()
                    * Field getField(String name)
    
                    * Field[] getDeclaredFields()
                      Field getDeclaredField(String name)
            */
    
            //Field[] getFields() 获取所有public修饰的成员变量
            Field[] fields = studentClass.getFields();
            for (Field field : fields) {
                System.out.println(field);
            }
    
            System.out.println("----------");
            //Field getField(String name)
            Field a = studentClass.getField("a");
            //获取成员变量a的值
            Student s = new Student();
            Object value = a.get(s);
            System.out.println(value);
            //设置a的值
            a.set(s, "张三");
            System.out.println(s);
    
            System.out.println("----------");
    
            //Field[] getDeclaredFields() 获取所有的成员变量
            Field[] declaredFields = studentClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println(declaredField);
            }
    
            System.out.println("----------");
    
            //Field getDeclaredField(String name)
            Field d = studentClass.getDeclaredField("d");
            //忽略访问权限修饰符
            d.setAccessible(true);//暴力反射
            Object value2 = d.get(s);
            System.out.println(value2);
        }
    }
    
    //运行结果
    public java.lang.String cn.ideal.domain.Student.a
    ----------
    null
    Student{name='null', age=0, a='张三', b='null', c='null', d='null'}
    ----------
    private java.lang.String cn.ideal.domain.Student.name
    private int cn.ideal.domain.Student.age
    public java.lang.String cn.ideal.domain.Student.a
    protected java.lang.String cn.ideal.domain.Student.b
    java.lang.String cn.ideal.domain.Student.c
    private java.lang.String cn.ideal.domain.Student.d
    ----------
    null
    
    package cn.ideal.reflect;
    
    import cn.ideal.domain.Student;
    
    import java.lang.reflect.Constructor;
    
    public class ReflectDemo3 {
        public static void main(String[] args) throws Exception {
            //获取Student的Class对象
            Class studentClass = Student.class;
    
            /*
                2. 获取构造方法们
                    * Constructor<?>[] getConstructors()
                    * Constructor<T> getConstructor(类<?>... parameterTypes)
    
                    * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
                    * Constructor<?>[] getDeclaredConstructors()
            */
    
            //Constructor<T> getConstructor(类<?>... parameterTypes)
            Constructor constructor = studentClass.getConstructor(String.class, int.class);
            System.out.println(constructor);
            //创建对象 带参
            Object student = constructor.newInstance("张三", 20);
            System.out.println(student);
    
            System.out.println("----------");
    
            Constructor constructor1 = studentClass.getConstructor();
            System.out.println(constructor1);
            //创建对象 不带参
            Object student1 = constructor1.newInstance();
            System.out.println(student1);
    
            //创建对象 不带参 (推荐方法)
            Object o = studentClass.newInstance();
            System.out.println(o);
        }
    }
    
    package cn.ideal.reflect;
    
    import cn.ideal.domain.Student;
    
    import java.lang.reflect.Method;
    
    public class ReflectDemo4 {
        public static void main(String[] args) throws Exception {
            //获取Student的Class对象
            Class studentClass = Student.class;
    
            /*
                3. 获取成员方法们:
                    * Method[] getMethods()
                    * Method getMethod(String name, 类<?>... parameterTypes)
    
                    * Method[] getDeclaredMethods()
                    * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
            */
    
            //获取指定名称的方法
            Method study_method = studentClass.getMethod("study");
            Student s = new Student();
            //执行方法
            study_method.invoke(s);
    
            Method study_method2 = studentClass.getMethod("study", String.class);
            //执行方法
            study_method2.invoke(s, "英语");
            System.out.println("----------");
    
            //获取所有public修饰的方法
            Method[] methods = studentClass.getMethods();
            for (Method method : methods) {
                System.out.println(method);
                String name = method.getName();
                System.out.println(name);
            }
    
            //获取类名
            String className = studentClass.getName();
            System.out.println(className);
        }
    }
    

    (四) 反射案例

    通过修改配置文件,达到不改变该类的任何代码,可以创建任意类的对象,可以执行任意方法,避免了每一次都修改类文件的缺点,同时提高了程序的扩展性

    * 实现:
    	1. 配置文件
    	2. 反射
    * 步骤:
    	1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
    	2. 在程序中加载读取配置文件
    	3. 使用反射技术来加载类文件进内存
    	4. 创建对象
    	5. 执行方法
    
    //pro.properties 自定义配置文件
    className=cn.ideal.domain.Student
    methodName=study
    
    package cn.ideal.reflect;
    
    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    public class ReflectTest {
        public static void main(String[] args) throws Exception {
            /*
                不改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
             */
    
            //1.加载配置文件
    
            //创建Properties对象
            Properties pro = new Properties();
            //加载配置文件,转换为一个集合
            //获取class目录下的配置文件
            ClassLoader classLoader = ReflectTest.class.getClassLoader();
            InputStream is = classLoader.getResourceAsStream("pro.properties");
            pro.load(is);
    
            //2.获取配置文件中定义的数据
            String className = pro.getProperty("className");
            String methodName = pro.getProperty("methodName");
    
            //3.加载该类进内存
            Class cls = Class.forName(className);
    
            //4.创建对象
            Object obj = cls.newInstance();
    
            //5.获取方法对象
            Method method = cls.getMethod(methodName);
    
            //6.执行方法
            method.invoke(obj);
        }
    
    

    我仅仅浅薄的谈了一下反射的基本知识,一些比较深入的理解由于篇幅问题,放在后面专篇讲解,感谢支持。确实有很多不足之处,也希望能与大家交流。

    结尾:

    如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !_

    如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)

    在这里的我们素不相识,却都在为了自己的梦而努力 ❤

    一个坚持推送原创Java技术的公众号:理想二旬不止

  • 相关阅读:
    Machine learning 第8周编程作业 K-means and PCA
    Machine learning 第7周编程作业 SVM
    Machine learning第6周编程作业
    Machine learning 第5周编程作业
    小M的作物 最小割最大流
    k-近邻算法 python实现
    编辑距离 区间dp
    Machine learning第四周code 编程作业
    MDK5报错missing closing quote
    HDU 5512
  • 原文地址:https://www.cnblogs.com/ideal-20/p/11236570.html
Copyright © 2011-2022 走看看