Java反射机制(1)

反射是框架设计的灵魂

软件框架:软件本成品,能够帮助我们提高开发效率。Spring,SpringMVC,Mybaties, Hadoop, Spark

反射的定义:讲类的各个组成部分封装为其他对象。这就是反射机制。


image.png

===========================================
Class字节码对象
反射可以帮助我们创建对象

获取类的字节码对象,有三种方式:

1.Source(源代码阶段):

Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象,多用于配置文件,将类名定义在配置文件中,读取文件,加载类
如:Class.forName("reflect.demo01.Animal");

2.Class阶段:类名.class

通过类名的属性class获取,多用于方法的参数的传递。
如 Animal.class

3.Runtime运行时阶段:对象名.getClass();

getClass()方法在Object类中定义着,多用于对象的获取字节码的方式。
如:
Animal animal = new Animal();
animal.getClass();

package reflect.demo01;

public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException {

        /**
         * 想执行任何对象的任何方法
         * 首先不知道对象,也不知道方法,此时可以用反射
         * 使用反射创建对象,需要获取字节码,三个阶段有不通的获取方式
         *
         */
        Animal animal = new Animal(); //创建一个对象

        //第一阶段:源代码阶段
        Class cls1 = Class.forName("reflect.demo01.Animal");  //用copy reference的方式,需要抛出异常
        //第二阶段:Class阶段
        Class cls2 = Animal.class;
        //第三阶段:Runtime阶段
        Class cls3 = animal.getClass();

        System.out.println(cls1 == cls2); //true
        System.out.println(cls2 == cls3); //true

    }
}

注意:
1.一个类对应在内存中对象的字节码对象,有且只有一个,以上三种方式获取的字节码对象都是同一个对象。
2.每个类都会有一个字节码对象

成员方法:
1.获取类的成员变量们
Field[] getFields() 获取类中被public关键字修饰的成员变量
Field getField(String name)获取类中指定名称的被public关键字修饰的成员变量

Field[] getDeclareFields()  获取类中所有成员变量(字段),不考虑权限修饰符
Field getDeclareField(String name)   获取类中指定的成员变量
注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值

格式:nameField.setAccessible(true);

     Field nameField = personClass.getDeclaredField("name");
    //暴力反射,能获取私有变量的值
    nameField.setAccessible(true);
    Person p = new Person();

    nameField.set(p, "迪丽热巴");
    System.out.println(p);

获取字段的目的:
获取值 field.get(对象)
设置值 field.set(对象,字段对应的值)

2.获取类的构造方法们
Constructor[] getConstructors():获取类中所有被public修饰的构造方法
Constructor[] getConstructors(类... parameterTypes):获取指定的被public修饰的构造方法

  Constructor[] getDeclaredConstructors()
  Constructor[] getDeclaredConstructors(类... parameterTypes)

3.获取类的成员方法们
Method[] getMethods():获取类中所有被public修饰的成员方法
Method getMethod(String name, 类... parameterTypes):获取类中指定名称的被public修饰的成员方法

Method[] getDeclaredMethods() 获取私有的方法
Method getDeclaredMethod(String name, 类...  parameterTypes)

4.获取类名
//获取Person类的字节码对象
Class personClass = Person.class;
//获取全类名 reflect.demo02.Person
System.out.println(personClass.getName());
//只获取类名 Person
System.out.println(personClass.getSimpleName());

package reflect.demo02;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 1.获取类的成员方法们
 *     Field[] getFields() 获取类中被public关键字修饰的成员变量
 *     Field getField(String name)  获取类中指定名称的被public关键字修饰的成员变量
 *
 *     Field[] getDeclaredFields()  获取类中所有成员变量(字段),不考虑权限修饰符
 *     Field getDeclaredField(String name)  获取类中指定的成员变量
 *     注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值
 *     格式:Field nameField = personClass.getDeclaredField("name");
 *         //暴力反射,能获取私有变量的值
 *         nameField.setAccessible(true);
 *         Person p = new Person();
 *
 *         nameField.set(p, "迪丽热巴");
 *         System.out.println(p);
 *
 *     获取字段:
 *      获取值:field.get(对象)
 *      设置值:field.set(对象,字段对应的值)
 */

public class Demo01 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取Person类的字节码对象
        Class personClass = Person.class;
        //获取全类名 reflect.demo02.Person
        System.out.println(personClass.getName());
        //只获取类名 Person
        System.out.println(personClass.getSimpleName());

    }

    /**
     * 获取类的成员方法们
     *     Method[] getMethods():获取类中所有被public修饰的成员方法
     *     Method getMethod(String name, 类... parameterTypes):获取类中指定名称的被public修饰的成员方法
     *
     *     Method[] getDeclaredMethods() 获取所有私有的方法,用到暴力反射
     *     Method getDeclaredMethod(String name, 类...  parameterTypes) 获取指定的私有方法
     *     执行方法:方法名.invoke(对象)
     *
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static void getMethodsFromClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        //获取Person类的字节码对象
        Class personClass = Person.class;
        //获取类中所有的被public修饰的成员方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取指定名称的被public修饰的成员方法
        Method m1 = personClass.getMethod("eat");
        System.out.println(m1);

        //获取指定名称带参数的被public修饰的成员方法
        Method m2 = personClass.getMethod("eat", String.class);
        System.out.println(m2);

        Person p = new Person();
        //获取一个无参数成员方法并执行(执行一个对象)
        m1.invoke(p);

        //获取一个有参数的成员方法并执行
        m2.invoke(p, "饭饭");

        //获取私有的方法,并执行
        Method m3 = personClass.getDeclaredMethod("eat", int.class);
        //通过暴力反射访问私有方法
        m3.setAccessible(true);
        m3.invoke(p, 5);
    }

    /**
     * 获取类的成员变量们:
     *     Field[] getFields() 获取类中被public关键字修饰的成员变量
     *     Field getField(String name)获取类中指定名称的被public关键字修饰的成员变量
     *
     *     Field[] getDeclareFields()  获取类中所有成员变量(字段),不考虑权限修饰符
     *     Field getDeclareField(String name)   获取类中指定的成员变量
     *     注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static void getFieldsFromClass() throws NoSuchFieldException, IllegalAccessException {
        //获取Person类的字节码对象
        Class personClass = Person.class;

        //通过Person类的字节码对象的getFields()方法,获取类中被public关键字修饰的成员变量:[nickName, tel]
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("==========");

        //Field getField(String name)  获取类中指定名称的被public关键字修饰的成员变量
        Field field = personClass.getField("nickName");
        System.out.println(field);

        Person p = new Person();
        System.out.println(p);

        //给p这个对象的nickName的值设置为老k
        field.set(p, "老k");
        System.out.println(p);

        //获取该字段的值
        Object o = field.get(p);
        System.out.println(o);

        System.out.println("==========================");
        //    Field[] getDeclareFields()  获取类中所有成员变量(字段),不考虑权限修饰符
        //    Field getDeclareField(String name)   获取类中指定的成员变量
        Field[] fieldsDeclared = personClass.getDeclaredFields();
        for (Field fieldDeclared : fields) {
            System.out.println(fieldDeclared);
        }

        Field nameField = personClass.getDeclaredField("name");
        //暴力反射,能获取私有变量的值
        nameField.setAccessible(true);


        nameField.set(p, "迪丽热巴");
        System.out.println(p);
    }

    /**
     * 获取类的构造方法们
     *       Constructor[] getConstructors():获取类中所有被public修饰的构造方法
     *       Constructor[] getConstructors(类... parameterTypes):获取指定的被public修饰的构造方法
     *
     *       Constructor[] getDeclaredConstructors() 获取私有的构造方法
     *       Constructor[] getDeclaredConstructors(类... parameterTypes)
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    public static void getConstructorsFromClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Person类的字节码对象
        Class personClass = Person.class;

        //获取Person类中的所有构造方法
        Constructor[] constructors = personClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        //获取指定的带参数的构造方法
        Constructor ct1 = personClass.getConstructor(String.class, int.class);
        System.out.println(ct1);
        //创建一个对象,赋值并且强制类型转换成Person对象
        Person p2 = (Person)ct1.newInstance("xm", 12);
        System.out.println(p2);


        //获取无参数的构造方法,创建对象
        Constructor ct2 = personClass.getConstructor();
        //创建一个对象,并且强制类型转换成Person对象
        Person p1 = (Person)ct2.newInstance();
        System.out.println(p1);


        //获取私有的构造方法,通过暴力反射创建对象
        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true);
        Person p3 = (Person)declaredConstructor.newInstance("xm");
        System.out.println(p3);
        System.out.println(declaredConstructor);
    }
}

你可能感兴趣的:(Java反射机制(1))