• 反射的概念 和基本使用(一) look


    1 反射

    什么是反射

    java反射 是指在运行状态中 对于任意一个类 我们都可以知到这个类的所有方法和属性 也可以调用其所有的方法和属性 这种动态获取的方式 我们称为 反射

    什么是class对象

    我们通过使用反射 就是通过Class类来实现的 Class 类的实例表示正在运行的 Java 应用程序中的类和接口。

    也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)

    反射的使用

    获取class对象的三种方式

    基本类
    /**
     *
     * @author : look-word
     * @date : 2022-04-05 20:49
     **/
    public class Student {
        private String username;
        private String gender;
    
        public  String getInfo() {
            this.setUsername("张三");
            this.setGender("男");
            return this.username+"="+this.gender;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    }
    
    测试代码如下
    /**
     * @author : look-word
     * @date : 2022-04-05 20:54
     **/
    public class Test {
        public static void main(String[] args) {
    
            /*
                1 创建对象 获取其class对象
             */
            Student student = new Student();
            Class<? extends Student> aClass = student.getClass();
            System.out.println(aClass.getSimpleName());
            /*
                2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
             */
            Class<? extends Student> bClass=Student.class;
            System.out.println(aClass == bClass?"两者是同一对象":"两者不是同一对象");
            /*
                3 通过Class类的forName方法获取
             */
            try {
                //  Class.forName(类的相对路径)
                Class<?> cClass = Class.forName("bean.Student");
                System.out.println(bClass == cClass?"两者是同一对象":"两者不是同一对象");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
    结果如下

    证明

    在运行期间 一个类只有一个class对象的产生

    常用的是第三次 清晰 明了 因为 在一个项目中 可能会产生 相同名字的类

    解决疑惑 为什么要是用 第三种

    第一种对象都有了还要反射干什么。

    第二种需要导入类的包,依赖太强,不导包就抛编译错误。

    第三种,一个字符串可以传入也可写在配置文件中等多种方法。

    获取Class类中的所有构造方法

    基本类
    public class Student {
        //---------------构造方法-------------------
        //(默认的构造方法)
        Student(String str){
            System.out.println("(默认)的构造方法 s = " + str);
        }
    
        //无参构造方法
        public Student(){
            System.out.println("调用了公有、无参构造方法执行了。。。");
        }
    
        //有一个参数的构造方法
        public Student(char name){
            System.out.println("姓名:" + name);
        }
    
        //有多个参数的构造方法
        public Student(String name ,int age){
            System.out.println("姓名:"+name+" 年龄:"+ age);//这的执行效率有问题,以后解决。
        }
    
        //受保护的构造方法
        protected Student(boolean n){
            System.out.println("受保护的构造方法 n = " + n);
        }
    
        //私有构造方法
        private Student(int age){
            System.out.println("私有的构造方法   年龄:"+ age);
        }
    }
    
    测试代码
    /**
     * 测试构造方法
     * @author : look-word
     * @date : 2022-04-05 21:18
     **/
    public class TestConstructor {
    
    /**
     * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
     *
     * 1.获取构造方法:
     * 		1).批量的方法:
     * 			public Constructor[] getConstructors():所有"公有的"构造方法
                public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
    
     * 		2).获取单个的方法,并调用:
     * 			public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
     * 			public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
     *
     * 			调用构造方法:
     * 			Constructor-->newInstance(Object... initargs)
    */
        public static void main(String[] args) throws Exception {
            Class<?> student = Class.forName("bean.Student");
            /*
                1 获取所有共有的构造方法
             */
            System.out.println("\n1 获取所有共有的构造方法");
            Constructor<?>[] constructors = student.getConstructors();
            for (Constructor<?> constructor : constructors) {
                System.out.println(constructor);
            }
    
            /*
                2 获取共有的无参构造方法 可以写 null 或者 不填
             */
            System.out.println("\n2 获取共有的无参构造方法 可以写 null 或者 不填");
            Constructor<?> constructor2 = student.getConstructor();
            constructor2.newInstance();
    
            /*
                3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int)
             */
            System.out.println("\n 3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int)");
            Constructor<?> constructor3 = student.getConstructor(String.class, int.class);
            constructor3.newInstance("张三",19);
    
            /*
                4 获取 私有给定参数的构造方法 私有 不给定参数 不传参数即可
             */
            Constructor<?> constructor4 = student.getDeclaredConstructor(int.class);
            /*
                获取私有的属性 或者构造方法是 需要 设置无障碍 俗称 暴力访问
                不设置 会出异常 java.lang.IllegalAccessException
             */
            constructor4.setAccessible(true);
            constructor4.newInstance(19);
        }
    }
    
    
    执行结果

    注意

    获取私有属性的时候 一定要设置无障碍

    setAccessible(true);

    不设置 会出异常 java.lang.IllegalAccessException

    newInstance(Object... initargs) 创建一个新实例
    使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

    每次是用 newInstance创建的对象 都是不同的对象 代表不同的实例

    操作成员变量

    基本类
     
    public class Student {
    	public Student(){
    		
    	}
    	//**********字段*************//
    	public String name;
    	protected int age;
    	char sex;
    	private String phoneNum;
    	
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", sex=" + sex
    				+ ", phoneNum=" + phoneNum + "]";
    	}
    }
    
    测试代码
    /**
     * @author : look-word
     * @date : 2022-04-05 21:55
     **/
    public class TestField {
    
    /*
     * 获取成员变量并调用:
     *
     * 1.批量的
     * 		1).Field[] getFields():获取所有的"公有字段"
     * 		2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
     * 2.获取单个的:
     * 		1).public Field getField(String fieldName):获取某个"公有的"字段;
     * 		2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
     *
     * 	 设置字段的值:
     * 		Field --> public void set(Object obj,Object value):
     * 					参数说明:
     * 					1.obj:要设置的字段所在的对象;
     * 					2.value:要为字段设置的值;
    */
        public static void main(String[] args) throws Exception{
            Class<?> aClass = Class.forName("bean.Student");
            Student student = new Student();
    
            /*
                获取所有的共有字段
             */
            System.out.println("-------------------获取所有的共有字段--------------------");
            Field[] fields = aClass.getFields();
            for (Field field : fields) {
                /*
                    filed => public java.lang.String bean.Student.username
                    filed => 成员变量
                 */
    
                /*
                   我理解为 给某个对象的 成员变量 赋值
                   当前的filed 为 username 因为这里只能获取为 共有属性的成员变量
                 * field.set(student,"zhangsan");
                 */
                field.set(student,"zhangsan");
                System.out.println(student);
                /*
                    field.get(student);
                    获取某student中的 field 的 内容
                 */
                Object o = field.get(student);
                System.out.println(o);
                /*
                 *  打印filed的内容 => public java.lang.String bean.Student.username
                 */
                System.out.println(field);
            }
    
            System.out.println("-------------------给私有字段赋值--------------------");
            Field phone = aClass.getDeclaredField("phone");
            phone.setAccessible(true);// 设置无障碍 
            phone.set(student,"110");// 赋值给student对象
    
            System.out.println("-------------------获取私有字段--------------------");
            Field phone1 = aClass.getDeclaredField("phone");
            phone1.setAccessible(true);// 设置无障碍
            System.out.println(phone1.get(student));//取出student对象中的phone属性的值
        }
    }
    
    注意

    在操作私有属性的时候 不管是获取还是设置值 都需要设置无障碍

    setAccessible(true);// 设置无障碍

  • 相关阅读:
    Spring Security教程之自定义Spring Security默认的403页面
    Spring Security教程之Spring Security实现访问控制
    Spring Security的HTTP基本验证示例
    Maven3+Struts2.3.1.2整合的Hello World例子
    将Flex嵌入到Jsp页面实例-基于FlexModule插件
    Java I/O之FilenameFilter类列举出指定路径下某个扩展名的文件
    Java I/O之用FilenameFilter实现根据文件扩展名删除文件
    Flex与Java通信之HttpService方式
    Flex与Java通信之RemoteObject方式
    Flex之理解Flash中的事件机制
  • 原文地址:https://www.cnblogs.com/look-word/p/16104362.html
Copyright © 2020-2023  润新知