• java反射机制


    什么是反射

      反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。简单的说就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。

    获取class文件对象的方式   

      Object类的getClass()方法
      数据类型的静态属性class
      Class类中的静态方法
          public static Class forName(String className)

            // 方式1
            Person p = new Person();
            Class c = p.getClass();
    
            Person p2 = new Person();
            Class c2 = p2.getClass();
    
            System.out.println(p == p2);// false
            System.out.println(c == c2);// true
    
            // 方式2
            Class c3 = Person.class;
            // int.class;
            // String.class;
            System.out.println(c == c3);
    
            // 方式3
            // ClassNotFoundException
            Class c4 = Class.forName("renxixao.Person");
       System.out.println(c
    == c4); } }

     通过反射获取构造方法并使用

    public class Person {
        private String name;
        int age;
        public String address;
    
        public Person() {
        }
    
        private Person(String name) {
            this.name = name;
        }
    
        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public Person(String name, int age, String address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public void show() {
            System.out.println("show");
        }
    
        public void method(String s) {
            System.out.println("method " + s);
        }
    
        public String getString(String s, int i) {
            return s + "---" + i;
        }
    
        private void function() {
            System.out.println("function");
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", address=" + address
                    + "]";
        }
    
    }
    
    /*
     * 通过反射获取构造方法并使用。
     */
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            
            // 获取字节码文件对象
            Class c = Class.forName("renxixao.Person");
    
            // public Constructor[] getConstructors():所有公共构造方法
            Constructor[] constructors = c.getConstructors();
            for (Constructor con : constructors) {
                System.out.println("公共构造方法:"+con);
             }
            
            // public Constructor[] getDeclaredConstructors():所有构造方法
            Constructor[] declaredConstructors = c.getConstructors();
            for (Constructor con : declaredConstructors) {
                System.out.println("所有构造方法:"+con);
             }
            // public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个构造方法
            // Class<?>... parameterTypes:获取的构造方法的构造参数个数及数据类型的class字节码文件对象
            Constructor con = c.getConstructor();// 返回构造方法对象
            // public T newInstance(Object... initargs)
            // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
            Object obj = con.newInstance();
            System.out.println(obj);
            Person p = (Person)obj;
            p.show();    
        }
    }

    运行结果

    公共构造方法:public renxixao.Person(java.lang.String,int,java.lang.String)
    公共构造方法:public renxixao.Person()
    所有构造方法:public renxixao.Person(java.lang.String,int,java.lang.String)
    所有构造方法:public renxixao.Person()
    Person [name=null, age=0, address=null]
    show

    /*
     * 通过反射去获取该构造方法并使用:
     * public Person(String name, int age, String address)
     */
    public class ReflectDemo2 {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("renxixao.Person");
            // 获取带参构造方法对象
            // public Constructor<T> getConstructor(Class<?>... parameterTypes)
            Constructor con = c.getConstructor(String.class, int.class,
                    String.class);
            // 通过带参构造方法对象创建对象
            // public T newInstance(Object... initargs)
            Object obj = con.newInstance("小明", 27, "北京");
            System.out.println(obj);
        }
    }

    Person [name=小明, age=27, address=北京]

    通过反射获取私有构造方法并使用

    /*
     * 需求:通过反射获取私有构造方法并使用
     * private Person(String name){}
     */
    public class ReflectDemo3 {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("renxixiao.Person");
    
            // 获取私有构造方法对象
            // NoSuchMethodException:每个这个方法异常
            // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
            Constructor con = c.getDeclaredConstructor(String.class);
    
            // 用该私有构造方法创建对象
            // IllegalAccessException:非法的访问异常。
            // 暴力访问
            con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
            Object obj = con.newInstance("小明");
            System.out.println(obj);
        }
    }

    获取私有构造时必须设置 con.setAccessible(true) 否则出现 IllegalAccessException:非法的访问异常。

    通过反射获取获取成员变量并使用

    /*
     * 通过发生获取成员变量并使用
     */
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("renxixiao.Person");
    
            // 获取所有的成员变量
            Field[] fields = c.getFields(); // 获取全部的成员变量
            Field[] declaredFields = c.getDeclaredFields(); // 获取私有的成员变量
            for (Field field : fields) {
            System.out.println("公共的成员变量"+field);
            }
            for (Field field : declaredFields) {
                System.out.println("私有的成员变量"+field);
            }
    
            // 通过无参构造方法创建对象
            Constructor con = c.getConstructor();
            Object obj = con.newInstance();
    
            // 获取单个的成员变量
            // 获取address并对其赋值
            Field addressField = c.getField("address");
            // public void set(Object obj,Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
            addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
            System.out.println(obj);
    
            // 获取name并对其赋值
            // NoSuchFieldException
            Field nameField = c.getDeclaredField("name");
            // IllegalAccessException
            nameField.setAccessible(true);
            nameField.set(obj, "小明");
            System.out.println(obj);
    
            // 获取age并对其赋值
            Field ageField = c.getDeclaredField("age");
            ageField.setAccessible(true);
            ageField.set(obj, 27);
            System.out.println(obj);
        }
    }

    全部的成员变量public java.lang.String renxixiao.Person.address
    私有的成员变量private java.lang.String renxixiao.Person.name
    私有的成员变量int renxixiao.Person.age
    私有的成员变量public java.lang.String renxixiao.Person.address
    Person [name=null, age=0, address=null]
    Person [name=null, age=0, address=北京]
    Person [name=小明, age=0, address=北京]
    Person [name=小明, age=27, address=北京]

    通过反射获取获取方法并使用

    /*
     * 通过发生获取方法并使用
     */
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("renxixiao.Person");
    
            // 获取所有的方法
            Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
            Method[] methodss = c.getDeclaredMethods(); // 获取自己的所有的方法
            for (Method method : methods) {
            System.out.println("公共方法"+method);
            }
            for (Method method : methodss) {
                System.out.println("所有的方法"+method);
                }
            Constructor con = c.getConstructor();
            Object obj = con.newInstance();
    
            
            // 获取单个方法并使用
            // public void show()
            // public Method getMethod(String name,Class<?>... parameterTypes)
            // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
            Method m1 = c.getMethod("show");
            // public Object invoke(Object obj,Object... args)
            // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
            m1.invoke(obj); // 调用obj对象的m1方法
            System.out.println("----------");
            // public void method(String s)
            Method m2 = c.getMethod("method", String.class);
            m2.invoke(obj, "hello");
            System.out.println("----------");
    
            // public String getString(String s, int i)
            Method m3 = c.getMethod("getString", String.class, int.class);
            Object objString = m3.invoke(obj, "hello", 100);
            System.out.println(objString);
            // String s = (String)m3.invoke(obj, "hello",100);
            // System.out.println(s);
            System.out.println("----------");
    
            // private void function()
            Method m4 = c.getDeclaredMethod("function");
            m4.setAccessible(true);
            m4.invoke(obj);
        }
    }

    公共方法public java.lang.String renxixiao.Person.toString()
    公共方法public java.lang.String renxixiao.Person.getString(java.lang.String,int)
    公共方法public void renxixiao.Person.method(java.lang.String)
    公共方法public void renxixiao.Person.show()
    公共方法public final void java.lang.Object.wait() throws java.lang.InterruptedException
    公共方法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 boolean java.lang.Object.equals(java.lang.Object)
    公共方法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()
    所有的方法public java.lang.String renxixiao.Person.toString()
    所有的方法private void renxixiao.Person.function()
    所有的方法public java.lang.String renxixiao.Person.getString(java.lang.String,int)
    所有的方法public void renxixiao.Person.method(java.lang.String)
    所有的方法public void renxixiao.Person.show()
    show
    ----------
    method hello
    ----------
    hello---100
    ----------
    function

  • 相关阅读:
    Mac下ssh连接远程服务器时自动断开问题
    解决php中json_decode的异常JSON_ERROR_CTRL_CHAR (json_last_error = 3)
    如何写.gitignore只包含指定的文件扩展名
    python操作mysql数据库
    php数组函数
    Python中字符串切片操作
    Python实现字符串反转的几种方法
    每个Android开发者都应该了解的资源列表
    Android Studio 入门指南
    一个优秀的Android应用从建项目开始
  • 原文地址:https://www.cnblogs.com/renxixao/p/11442115.html
Copyright © 2020-2023  润新知