• Java API —— 反射


    1、类加载器

        1)类的加载
            · 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
            · 加载 :就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
            · 连接:
                · 验证 是否有正确的内部结构,并和其他类协调一致
                · 准备 负责为类的静态成员分配内存,并设置默认初始化值
                · 解析 将类的二进制数据中的符号引用替换为直接引用
            · 初始化:就是我们以前讲过的初始化步骤
        2)类初始化时机             

      · 创建类的实例
      · 访问类的静态变量,或者为静态变量赋值
      · 调用类的静态方法
      · 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
      · 初始化某个类的子类
      · 直接使用java.exe命令来运行某个主类

      3)类加载器
            · 负责将.class文件加载到内在中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
            · 类加载器的组成
                · Bootstrap ClassLoader 根类加载器
                · Extension ClassLoader 扩展类加载器
                · Sysetm ClassLoader 系统类加载器
        4)获取Class文件对象的三种方式
    Person类:
    package cn.itcast_01;
    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
                    + "]";
        }
    }

    测试类:

    package cn.itcast_01;
    /*
     * 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
     * 
     * Person p = new Person();
     * p.使用
     * 
     * 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
     * Class类:
     *         成员变量    Field
     *         构造方法    Constructor
     *         成员方法    Method
     * 
     * 获取class文件对象的方式:
     * A:Object类的getClass()方法
     * B:数据类型的静态属性class
     * C:Class类中的静态方法
     *         public static Class forName(String className)
     * 
     * 一般我们到底使用谁呢?
     *         A:自己玩    任选一种,第二种比较方便
     *         B:开发    第三种
     *             为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
     */
    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            // 方式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("cn.itcast_01.Person");
            System.out.println(c == c4);
        }
    }
    2、反射
        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
        要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
        1)通过反射获取构造方法并使用
            · 获取构造方法
        getConstructors
        getDeclaredConstructors
            · 创建对象
        newInstance()
        con.newInstance(“zhangsan", 20);
    例子1:
    package cn.itcast_02;
    import java.lang.reflect.Constructor;
    import cn.itcast_01.Person;
    /*
     * 通过反射获取构造方法并使用。
     */
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("cn.itcast_01.Person");
            // 获取构造方法
            // public Constructor[] getConstructors():所有公共构造方法
            // public Constructor[] getDeclaredConstructors():所有构造方法
            // Constructor[] cons = c.getDeclaredConstructors();
            // for (Constructor con : cons) {
            // System.out.println(con);
            // }
            // 获取单个构造方法
            // public Constructor<T> getConstructor(Class<?>... parameterTypes)
            // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
            Constructor con = c.getConstructor();// 返回的是构造方法对象
            // Person p = new Person();
            // System.out.println(p);
            // public T newInstance(Object... initargs)
            // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
            Object obj = con.newInstance();
            System.out.println(obj);
            
            // Person p = (Person)obj;
            // p.show();
        }
    }

     例子2:

    package cn.itcast_02;
    import java.lang.reflect.Constructor;
    /*
     * 需求:通过反射去获取该构造方法并使用:
     * public Person(String name, int age, String address)
     * 
     * Person p = new Person("林青霞",27,"北京");
     * System.out.println(p);
     */
    public class ReflectDemo2 {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("cn.itcast_01.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);
        }
    }

    例子3:

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

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

            · 获取所有成员
        getFields
               getDeclaredFields
            · 获取单个成员
        getField
        getDeclaredField
            · 修改成员的值
        set(Object obj,Object value) :将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
    例子:
    package cn.itcast_03;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    /*
     * 通过发生获取成员变量并使用
     */
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("cn.itcast_01.Person");
            // 获取所有的成员变量
            // Field[] fields = c.getFields();
            // Field[] fields = c.getDeclaredFields();
            // for (Field field : fields) {
            // System.out.println(field);
            // }
            /*
             * Person p = new Person(); p.address = "北京"; System.out.println(p);
             */
            // 通过无参构造方法创建对象
            Constructor con = c.getConstructor();
            Object obj = con.newInstance();
            System.out.println(obj);
            // 获取单个的成员变量
            // 获取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);
        }
    }

      3)通过反射获取成员方法并使用

            · 获取所有方法
        getMethods
        getDeclaredMethods
            · 获取单个方法
        getMethod
        getDeclaredMethod
            · 暴力访问
        method.setAccessible(true);
    例子1:
    package cn.itcast_04;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    public class ReflectDemo {
        public static void main(String[] args) throws Exception {
            // 获取字节码文件对象
            Class c = Class.forName("cn.itcast_01.Person");
            // 获取所有的方法
            // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
            // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
            // for (Method method : methods) {
            // System.out.println(method);
            // }
            Constructor con = c.getConstructor();
            Object obj = con.newInstance();
            /*
             * Person p = new Person(); p.show();
             */
            // 获取单个方法并使用
            // public void show()
            // public Method getMethod(String name,Class<?>... parameterTypes)
            // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
            Method m1 = c.getMethod("show");
            // obj.m1(); // 错误
            // 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);
        }
    }

    例子2:我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?

    package cn.itcast.test;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    /*
     * 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
     */
    public class ArrayListDemo {
        public static void main(String[] args) throws NoSuchMethodException,
                SecurityException, IllegalAccessException,
                IllegalArgumentException, InvocationTargetException {
            // 创建集合对象
            ArrayList<Integer> array = new ArrayList<Integer>();
            // array.add("hello");
            // array.add(10);
            Class c = array.getClass(); // 集合ArrayList的class文件对象
            Method m = c.getMethod("add", Object.class);
            m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
            m.invoke(array, "world");
            m.invoke(array, "java");
            System.out.println(array);
        }
    }
    例子3:写一个方法,public void setProperty(Object obj, String propertyName, Object value){},此方法可将obj对象中名为propertyName的属性的值设置为value。
    Tool类:
    package cn.itcast.test;
    import java.lang.reflect.Field;
    public class Tool {
        public void setProperty(Object obj, String propertyName, Object value)
                throws NoSuchFieldException, SecurityException,
                IllegalArgumentException, IllegalAccessException {
            // 根据对象获取字节码文件对象
            Class c = obj.getClass();
            // 获取该对象的propertyName成员变量
            Field field = c.getDeclaredField(propertyName);
            // 取消访问检查
            field.setAccessible(true);
            // 给对象的成员变量赋值为指定的值
            field.set(obj, value);
        }
    }

     测试类:

    package cn.itcast.test;
    public class ToolDemo {
        public static void main(String[] args) throws NoSuchFieldException,
                SecurityException, IllegalArgumentException, IllegalAccessException {
            Person p = new Person();
            Tool t = new Tool();
            t.setProperty(p, "name", "林青霞");
            t.setProperty(p, "age", 27);
            System.out.println(p);
            System.out.println("-----------");
            Dog d = new Dog();
            t.setProperty(d, "sex", '男');
            t.setProperty(d, "price", 12.34f);
            System.out.println(d);
        }
    }
    class Dog {
        char sex;
        float price;
        @Override
        public String toString() {
            return sex + "---" + price;
        }
    }
    class Person {
        private String name;
        public int age;
        @Override
        public String toString() {
            return name + "---" + age;
        }
    }
     
     
     
     
     
  • 相关阅读:
    MySQL 字符集
    MySQL 存储引擎
    MySQL 常用函数
    MySQL 中的运算符
    MySQL 支持的数据类型
    SQL DCL 数据控制语句
    SQL DML 数据操纵语句
    SQL DDL 数据定义语句
    SQL 数据库结构化查询语言
    MySQL 服务常用操作命令
  • 原文地址:https://www.cnblogs.com/yangyquin/p/5230372.html
Copyright © 2020-2023  润新知