• 反射之基础


    1定义

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

    反射机制主要提供了以下功能: 

    • 在运行时判断任意一个对象所属的类;

    • 在运行时构造任意一个类的对象;

    • 在运行时判断任意一个类所具有的成员变量和方法;

    • 在运行时调用任意一个对象的方法;

    • 生成动态代理。

    在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
    Class类:代表一个类。
    Field 类:代表类的成员变量(成员变量也称为类的属性)。
    Method类:代表类的方法。
    Constructor 类:代表类的构造方法。
    Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

    2核心API

    Class类是Reflection API 中的核心类,它有以下方法
    getName():获得类的完整名字。
    getFields():获得类的public类型的属性。
    getDeclaredFields():获得类的所有属性。
    getMethods():获得类的public类型的方法。
    getDeclaredMethods():获得类的所有方法。
    getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
    getConstructors():获得类的public类型的构造方法。
    getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
    newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

    2.1基本操作:

    实体类:User.java

    package com.wfz;
    
    public class User {
        public String name;
        private String password;
        private Integer age;
        private String addr;
    
        public User() {
        }
    
        public User(String name) {
            this.name = name;
        }
    
        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        public User(String name, String password, Integer age, String addr) {
            this.name = name;
            this.password = password;
            this.age = age;
            this.addr = addr;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getAddr() {
            return addr;
        }
    
        public void setAddr(String addr) {
            this.addr = addr;
        }
    }

    测试类:

    import java.lang.reflect.*;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
            Class c1 = Class.forName("com.wfz.User");//java.lang.String
            Class c2 = User.class;
            User obj = new User();
            Class c3 = obj.getClass();
            Class cs[] = {java.lang.String.class};
    //      Class cs[] = {java.lang.String.class,java.lang.Integer.class};
    
            System.out.println("构造方法-----------------------------------------------------");
    
            Constructor cst1 = c1.getConstructor(cs);
            System.out.println("1、通过参数获取指定Class对象的构造方法:");
            System.out.println(cst1.toString());
    
            Constructor cst2 = c1.getDeclaredConstructor(cs);
            System.out.println("2、通过参数获取指定Class对象所表示的类或接口的构造方法:");
            System.out.println(cst2.toString());
    
            Constructor cst3 = c1.getEnclosingConstructor();
            System.out.println("3、获取本地或匿名类Constructor 对象,它表示基础类的立即封闭构造方法。");
            if (cst3 != null) System.out.println(cst3.toString());
            else System.out.println("-- 没有获取到任何构造方法!");
    
            Constructor[] csts = c1.getConstructors();
            System.out.println("4、获取指定Class对象的所有构造方法:");
            for (int i = 0; i < csts.length; i++) {
                System.out.println(csts[i].toString());
            }
    
            System.out.println("接口-----------------------------------------------------");
    
            Type types1[] = c1.getGenericInterfaces();
            System.out.println("1、返回直接实现的接口:");
            for (int i = 0; i < types1.length; i++) {
                System.out.println(types1[i].toString());
            }
    
            Type type1 = c1.getGenericSuperclass();
            System.out.println("2、返回直接超类:");
            System.out.println(type1.toString());//不能私有
    
            Class[] cis = c1.getClasses();
            System.out.println("3、返回超类和所有实现的接口:");
            for (int i = 0; i < cis.length; i++) {
                System.out.println(cis[i].toString());
            }
    
            Class cs1[] = c1.getInterfaces();
            System.out.println("4、实现的接口:");
            for (int i = 0; i < cs1.length; i++) {
                System.out.println(cs1[i].toString());
            }
    
            System.out.println("变量-----------------------------------------------------");
            Field fs1[] = c1.getFields();
            System.out.println("1、类或接口的所有可访问公共字段:");
            for (int i = 0; i < fs1.length; i++) {
                System.out.println(fs1[i].toString());
            }
    
            Field f1 = c1.getField("name");//不能私有
            System.out.println("2、类或接口的指定已声明指定公共成员字段:");
            System.out.println(f1.toString());
    
            Field[] f = c1.getDeclaredFields();
            System.out.println("3、类或接口所声明的所有字段:");
            System.out.println(Modifier.toString(c1.getModifiers()) + " class " + c1.getSimpleName() + ":");
            for (Field p : f) {
                System.out.println(Modifier.toString(p.getModifiers()) + "   " + p.getType().getSimpleName() + "   " + p.getName() + ";");
            }
    
            Field fname = c1.getDeclaredField("name");
            System.out.println("4、类或接口的指定已声明指定字段:");
            System.out.println(fname.toString());
    
            System.out.println("方法-----------------------------------------------------");
            Method m1[] = c1.getMethods();
            System.out.println("1、返回类所有的公共成员方法:");
            for (int i = 0; i < m1.length; i++) {
                System.out.println(m1[i].toString());
            }
    
            Method m2 = c1.getMethod("getName", new Class[]{});
            System.out.println("2、返回指定公共成员方法:");
            System.out.println(m2.toString());
        }
    }

    结果:

    构造方法-----------------------------------------------------
    1、通过参数获取指定Class对象的构造方法:
    public com.wfz.User(java.lang.String)
    2、通过参数获取指定Class对象所表示的类或接口的构造方法:
    public com.wfz.User(java.lang.String)
    3、获取本地或匿名类Constructor 对象,它表示基础类的立即封闭构造方法。
    -- 没有获取到任何构造方法!
    4、获取指定Class对象的所有构造方法:
    public com.wfz.User(java.lang.String,java.lang.String,java.lang.Integer,java.lang.String)
    public com.wfz.User(java.lang.String,java.lang.Integer)
    public com.wfz.User(java.lang.String)
    public com.wfz.User()
    接口-----------------------------------------------------
    1、返回直接实现的接口:
    2、返回直接超类:
    class java.lang.Object
    3、返回超类和所有实现的接口:
    4、实现的接口:
    变量-----------------------------------------------------
    1、类或接口的所有可访问公共字段:
    public java.lang.String com.wfz.User.name
    2、类或接口的指定已声明指定公共成员字段:
    public java.lang.String com.wfz.User.name
    3、类或接口所声明的所有字段:
    public class User:
    public   String   name;
    private   String   password;
    private   Integer   age;
    private   String   addr;
    4、类或接口的指定已声明指定字段:
    public java.lang.String com.wfz.User.name
    方法-----------------------------------------------------
    1、返回类所有的公共成员方法:
    public java.lang.String com.wfz.User.getName()
    public void com.wfz.User.setName(java.lang.String)
    public java.lang.String com.wfz.User.getPassword()
    public void com.wfz.User.setPassword(java.lang.String)
    public java.lang.String com.wfz.User.getAddr()
    public void com.wfz.User.setAge(java.lang.Integer)
    public void com.wfz.User.setAddr(java.lang.String)
    public java.lang.Integer com.wfz.User.getAge()
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    2、返回指定公共成员方法:
    public java.lang.String com.wfz.User.getName()

    2.2相关操作

    实体类:

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class RefDemo {
    
        public int add(int a, int b) {
            return a + b;
        }
    
        public String echo(String s) {
            return "字符串:" + s;
        }
    
        public Object copy(Object obj) throws Exception {
            Class c = obj.getClass();
            //System.out.println("Class:" + c.getName());
            //Object o = c.getConstructor(new Class[]{}).newInstance(new Object[]{});
            Object o = c.newInstance();
            Field[] arr = c.getDeclaredFields();
            for (Field f : arr) {
                String fname = f.getName();
                // 获得和属性对应的setXXX()方法的名字
                String setname = "set" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
                // 获得和属性对应的getXXX()方法的名字
                String getname = "get" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
                // 获得和属性对应的getXXX()方法
                Method getmethod = c.getMethod(getname, new Class[]{});
                // 获得和属性对应的setXXX()方法
                Method setmethod = c.getMethod(setname, new Class[]{f.getType()});
                // 调用原对象的getXXX()方法
                Object value = getmethod.invoke(obj, new Object[]{});//形参值value
                //System.out.println(fname + ":" + value);
                // 调用拷贝对象的setXXX()方法
                setmethod.invoke(o, new Object[]{value});
            }
            return o;
        }
    
    }

    测试类:

    public class Main {
    
        public static void main(String[] args) throws Exception {
            Class c1 = Class.forName("com.wfz.User");//java.lang.String
            Field fname = c1.getDeclaredField("name");
            
            //反射调用对象方法
            Class rd = RefDemo.class;
            Object ob = rd.newInstance();
            //得到add方法
            Method add = rd.getMethod("add", new Class[]{int.class, int.class});//不能私有
            //带参数调用add
            Object ret = add.invoke(ob, new Object[]{new Integer(1), new Integer(2)});
            Integer retint = (Integer) ret;
            System.out.println(retint);//3
            Method echo = rd.getMethod("echo", new Class[]{String.class});//不能私有
            //带参数调用add
            Object rets = echo.invoke(ob, new Object[]{new String("test")});
            System.out.println(rets);//字符串:test
    
            //运行复制对象
            User user = new User();
            user.setName("nametest");
            RefDemo cd = new RefDemo();
            User newuser = (User) cd.copy(user);
            System.out.println(newuser.getName());//nametest
    
            //变更field内容
            Object objuser = c1.newInstance();
            Field fieldname = c1.getDeclaredField("name");
            fname.set(objuser, "liang");//不能私有
            System.out.println("name:" + fieldname.get(objuser));//name:liang
        }
    }

    3.数组

    public static void main(String[] args) throws Exception {
            //一维数组
            Class c = Class.forName("java.lang.String");
            // 创建一个长度为10的字符串数组
            Object array = Array.newInstance(c, 10);
            // 把索引位置为5的元素设为"hello world"
            Array.set(array, 5, "hello world");
            // 获得索引位置为5的元素的值
            String five = (String) Array.get(array, 5);
            System.out.println(five);//hello world
    
            //三维数组
            int[] dims = new int[]{5, 10, 15};
            //创建一个具有指定的组件类型和维度的新数组。
            Object arr = Array.newInstance(Integer.TYPE, dims);
    
            Object arrayObj = Array.get(arr, 1);
            Class<?> cls = arrayObj.getClass().getComponentType();
            System.out.println(cls);//class [I
            arrayObj = Array.get(arrayObj, 2);
            Array.setInt(arrayObj, 3, 4);
            int arrayCast[][][] = (int[][][]) arr;
            System.out.println(arrayCast[1][2][3]);//4
        }
  • 相关阅读:
    VMware centos7 网络设置
    PostgreSQL 执行进度监控:VACUUM 、ANALYZE、CREATE INDEX 、CLUSTER、Base Backup
    PostgreSQL: Hash Semi Join
    事务隔离级别实验--SQL在等待锁结束之后,是否会再次获取快照
    转:PostgreSQL WAL解析与闪回的一些想法
    PostgreSQL Event trigger 使用记录:阻断危险SQL、记录DDL操作
    转:PgSQL · 特性分析 · Write-Ahead Logging机制浅析
    mongo使用问题记录
    goldplayer h265播放器
    在线书籍
  • 原文地址:https://www.cnblogs.com/manusas/p/6698863.html
Copyright © 2020-2023  润新知