• java 反射


      反射是实现java语言动态性的方法,一般写的程序,所以新建的对象通过程序员写死的,但是有了反射,可以在程序运行期间动态的实例化一些对象,调用一些方法。

    反射的实现原理:当类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。class对象相当于这个类的建设图纸,通过这个图纸,我们可以动态查找这个类的类名,属性,方法,然后实例化调用他们;

    class对象和一般new出来的对象有什么区别:1,class对象是保存类的整个结构信息,它保存的是这个类有什么属性,方法,叫什么名字等等,属性是没有具体的值的,主要作用是用来查询类的结构信息;2,new 的对象是表示或封装一些数据,保存每个属性的值,方法,是用来操作数据的;

    注意:因为每个类的结构信息都是一样的,所以每个类只有一个class对象;

    package com.test.bean;
    
    public class User {
        
        private int id;
        private int age;
        private String uname;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getUname() {
            return uname;
        }
        
        public void setUname(String uname) {
            this.uname = uname;
        }
        
        public void setUname() {
            this.uname = "高淇";
        }
        
        public User(int id, int age, String uname) {
            super();
            this.id = id;
            this.age = age;
            this.uname = uname;
        }
        
        //javabean必须要有无参的构造方法!
        public User() {
        }
    }
    下面用到的user类

    1,获取class类的方法:

    • class.forName(类的路径)
    • 对象.class
    • 路径.getClass()

    具体看代码:

    public class Demo01 {
        
        public static void main(String[] args) {
            String path = "com.test.bean.User";
            
            try {
                
                Class clazz = Class.forName(path);
                //对象是表示或封装一些数据。  一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。
                //这个Class对象就像一面镜子一样,通过这面镜子我可以看到对应类的全部信息。
                System.out.println(clazz.hashCode());
                
                //class.forName(类的路径)
                Class clazz2 = Class.forName(path);    
                System.out.println(clazz2.hashCode());
                
                //对象.class
                Class strClazz = String.class;
                
                //路径.getClass()
                Class strClazz2 = path.getClass(); 
                
                
                //一个类只对应一个Class对象
                System.out.println(strClazz==strClazz2);
                Class intClazz =int.class;
                int[] arr01 = new int[10];
                int[][] arr02 = new int[30][3];
                int[] arr03 = new int[30];
                double[] arr04 = new double[10];
                
                System.out.println(arr01.getClass().hashCode());
                System.out.println(arr02.getClass().hashCode());
                System.out.println(arr03.getClass().hashCode());
                System.out.println(arr04.getClass().hashCode());
                
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
        
    }

    运行结果:

    2,应用反射的API,获取类的信息(类的名字、属性、方法、构造器等)

    直接看代码和注释

    public class Demo02 {
        public static void main(String[] args) {
            String path = "com.test.bean.User";
            
            try {
                Class clazz = Class.forName(path);
                
                //获取类的名字
                System.out.println(clazz.getName());//获得包名+类名:com.test.bean.User
                System.out.println(clazz.getSimpleName());    //获的类名:User
                
                //获取属性信息
    //            Field[] fields = clazz.getFields(); //只能获得public的field
                Field[] fields = clazz.getDeclaredFields();//加Declared的方法都获得所有的field
                Field f = clazz.getDeclaredField("uname");
                System.out.println(fields.length);
                for(Field temp:fields){
                    System.out.println("属性:"+temp);
                }
                //获取方法信息
                Method[] methods = clazz.getDeclaredMethods();
                Method m01 = clazz.getDeclaredMethod("getUname", null);
                //如果方法有参,则必须传递参数类型对应的class对象
                Method m02 = clazz.getDeclaredMethod("setUname", String.class); 
                for(Method m:methods){
                    System.out.println("方法:"+m);
                }
                
                //获得构造器信息
                Constructor[] constructors = clazz.getDeclaredConstructors();
                Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
                System.out.println("获得构造器:"+c);
                for(Constructor temp:constructors){
                    System.out.println("构造器:"+temp);
                }    
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    ,3,通过反射API动态的操作:构造器、方法、属性

    • 主要通过newInstance()调用构造方法实例化对象,
    • 获取方法method后通过method.invoke()调用方法,
    • 获得属性f后通过f.set(对象, 值)的方式设置对应对象的属性值;
    package com.test;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    import com.test.bean.User;
    
    public class Demo03 {
        public static void main(String[] args) {
    
            String path = "com.bjsxt.test.bean.User";
            
            try {
                Class<User> clazz = (Class<User>) Class.forName(path);
                
                //通过反射API调用构造方法,构造对象
                User u = clazz.newInstance();    //其实是调用了User的无参构造方法
                System.out.println(u);
                
                Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
                User u2 = c.newInstance(1001,18,"高淇二");
                System.out.println(u2.getUname());
                
                //通过反射API调用普通方法
                User u3 = clazz.newInstance();
                Method method = clazz.getDeclaredMethod("setUname", String.class);
                method.invoke(u3, "高淇三");   //u3.setUname("高淇三");
                System.out.println(u3.getUname());
                
                //通过反射API操作属性
                User u4 = clazz.newInstance();
                Field f = clazz.getDeclaredField("uname");
                f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问
                f.set(u4, "高淇四");        //通过反射直接写属性
                System.out.println(u4.getUname());    //通过反射直接读属性的值
                System.out.println(f.get(u4));     
            } catch (Exception e) {
                e.printStackTrace();
            }     
        }
    }

    当需要大量修改私有属性 f 时,通过f.setAccessible(true);这个属性不需要做安全检查了,可以直接访问,可以大大提高程序运行的速度;

  • 相关阅读:
    centos7上安装memcached以及PHP安装memcached扩展(二)
    centos7上安装memcached以及PHP安装memcached扩展(一)
    centos7上安装redis以及PHP安装redis扩展(二)
    centos7上安装redis以及PHP安装redis扩展(一)
    Redis Desktop Manager无法连接虚拟机中启动的redis服务问题排查步骤
    CentOS 7设置开机启动服务,添加自定义系统服务
    delphi 选择文件夹目录保存
    mysql drop database ERROR 2013
    delphi 在别的方法 调用keypress事件
    delphi Inc Dec用法
  • 原文地址:https://www.cnblogs.com/zdl2234/p/11234003.html
Copyright © 2020-2023  润新知