Java反射机制-Spring反射机制

什么是反射?

(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。 本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了, 而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到, 所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性, 不需要提前在编译期知道运行的对象是谁。

反射:能够分析类能力的程序叫做反射

翻译成人话:能够分析类信息的能力的程序叫做反射。

什么是类的信息?

简单的来说比如 属性、方法、构造器等等。。。

举例:

Class class1 = Class.forName("reflect.Person");
System.out.println(class1);
Field[] fields = class1.getFields();
   for (Field field : fields) {
            System.out.println(field);
      }

那么一个新的问题就来了,我们明明可以通过new 一个对象来获取类信息,那么我们为什么要使用反射呢?

我们在这里说一个实际的列子,比如说我们以前使用过的servlet框架,·那么在servlet框架当中我们写过JBDC类,在这个类当中我们引入了一个mysql.jar包,那么这个jar包是怎么起作用的呢,请大家请注意,我们的servlet类当中课没有main方法,那我们的servlet类是如何启动的呢?如何加载到我们的JVM当中呢?

答案就是使用了反射,大家看一个东西:

Java反射机制-Spring反射机制_第1张图片

 从上面可以看到,正式因为有了反射,我们才能将他们加载如JVM当中。

那么反射是如何工作的呢?

要想理解反射是如何工作的我们先来看类的声明周期类的生命周期:

Java反射机制-Spring反射机制_第2张图片

 Java反射机制-Spring反射机制_第3张图片

 

好处:

1.在程序的运行过程中,来操作这些对象

String str = "123";
str.

我们对 . 会出现很多的方法,这其实就是内部就是使用的是反射机制,你定义了一个字符串,那么他会把字符串的字节码文件加载进内存,在内存当中有一个class类对象,class对象已将所有的方法都抽取出来封装在method[]数组当中,所以我们能够 . 出这么多的程序。

*获取class对象的方式

1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象;

多用于配置文件,将类名定义在配置文件当中,读取文件,加载类

Java反射机制-Spring反射机制_第4张图片

2.类名.class:通过类名的class获取

多用于参数的传递

Java反射机制-Spring反射机制_第5张图片

3.对象.getClass():getClass()方法在object类当中定义着 

多用于对象获取字节码的方式

Java反射机制-Spring反射机制_第6张图片

 首先定义一个person类,内部定义好成员变量,构造方法和成员方法:

package com.haijiao12138.demo.spring.reflection;

/**
 * @author: haijiao12138
 * @ClassName: Person
 * @description: TODO
 * @date: 2021/8/15 2:06
 *
 */
public class Person {
    private String nameString;
    private int age;

    public Person() {

    }

    public Person(String nameString, int age) {
        this.nameString = nameString;
        this.age = age;
    }

    public String getNameString() {
        return nameString;
    }

    public void setNameString(String nameString) {
        this.nameString = nameString;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [nameString=" + nameString + ", age=" + age + "]";
    }
}

 定义测试类:

package com.haijiao12138.demo.spring.reflection;

/**
 * @author: haijiao12138
 * @ClassName: RefulectDemo1
 * @description: TODO
 * @date: 2021/8/15 2:07
 *
 */
public class RefulectDemo1 {
    /**
     *1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
     *2.类名.class:通过类名的class获取
     *3.对象.getClass(): getClass()方法在object类当中定义着
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws Exception {
        // 1.Class.forName("全类名"):
        Class class1 = Class.forName("com.haijiao12138.demo.spring.reflection.Person");
        System.out.println(class1);

        //2.类名.class:通过类名的class获取
        Class class2 = Person.class;
        System.out.println(class2);

        //3.对象.getClass()
        Person person = new Person();
        Class class3 = person.getClass();
        System.out.println(class3);

        System.out.println(class1 == class2);
        System.out.println(class2==class3);

    }
}

用 == 进行比较:控制台输出结果:

Java反射机制-Spring反射机制_第7张图片

结论:

同一类加载器加载的文件(*.class)在一次程序运行过程中,只会被加载一次,不论你通过哪种方式获取的class对象都是同一个;

反射创造*class对象后,类对象的功能如下:可以在Idea中测试:

· 1.获取成员变量们

1.Field[] getFields() :获取所有public修饰的成员变量

2.Field getField(String name):获取指定名称的

3.Field[] getDeclaredFilds():获取所有的成员变量,不考虑修饰符

4.Field getDeclaredField(String name)

2.获取构造方法们

1.Constructor[] getConstructors()

2.Constructor getConstructor(类...parameterTypes)

3.Constructor[] getDeclaredConstructors()

4.Constructor getDeclaredConstructors(类...parameterTypes)

3.获取方法名

1.Method[] getMethod()

2.Method getMethod(String name,类... parameterTypes)

3.Method[] getDeclaredMethod()

4.Method getDeclaredMethod(String name,类... parameterTypes)

4.获取类名

String getName()

Field成员变量
操作
1.设置值
void set(Object obj,Object value)
2.获取值
get(Object obj)
3.忽略安全访问修饰符的安全检查
setAccessible(true) //暴力反射 ---》private

package com.haijiao12138.demo.spring.reflection;

/**
 * @author: 候苑博
 * @ClassName: Person
 * @description: TODO
 * @date: 2021/8/15 2:06
 *
 */
public class Person {
    private String nameString;
    public String name;
    private int age;
    public String age1;

    public Person() {

    }

    public Person(String nameString, int age) {
        this.nameString = nameString;
        this.age = age;
    }

    public String getNameString() {
        return nameString;
    }

    public void setNameString(String nameString) {
        this.nameString = nameString;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "nameString='" + nameString + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", age1='" + age1 + '\'' +
                '}';
    }
}

 

package com.haijiao12138.demo.spring.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author: haijiao12138
 * @ClassName: RefulectDemo1
 * @description: TODO
 * @date: 2021/8/15 2:07
 *
 */
public class RefulectDemo1 {
    /**
     *1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
     *2.类名.class:通过类名的class获取
     *3.对象.getClass(): getClass()方法在object类当中定义着
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

        //0.获取Person的Class对象
        Class personClass = Person.class;
        /*
             1. 获取成员变量们
                 * Field[] getFields()
                 * Field getField(String name)

                 * Field[] getDeclaredFields()
                 * Field getDeclaredField(String name)

         */
        //1.Field[] getFields()获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("------------");
        //2.Field getField(String name)
        Field a = personClass.getField("age1");
        System.out.println(a);
        //获取成员变量a 的值
        Person p = new Person();
        System.out.println(p);
        Object value = a.get(p);
        System.out.println(value);
        //设置a的值
        a.set(p,"张三");
        System.out.println(p);

        System.out.println("===================");

        //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("age");
        //忽略访问权限修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2 = d.get(p);
        System.out.println(value2);
    }
}

Constructor访问构造方法
*创建对象
*T newInstance(Object... initarges)
*如果使用空参数构造方法,此操作可以简化:class对象的newInstance方法

package com.haijiao12138.demo.spring.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author: haijiao12138
 * @ClassName: RefulectDemo1
 * @description: TODO
 * @date: 2021/8/15 2:07
 *
 */
public class RefulectDemo1 {
    /**
     *1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
     *2.类名.class:通过类名的class获取
     *3.对象.getClass(): getClass()方法在object类当中定义着
     * @throws ClassNotFoundException
     */
 
    public static void main(String[] args) throws Exception {
        //0.获取Person的class对象
        Class personClass = Person.class;

        //因为构造器的方法名称是相同的,不同的是参数列表,所以我们可以根据不同的参数列表来找到构造器
        Constructor constructor = personClass.getConstructor(String.class,int.class);
        System.out.println(constructor);
        //创建对象
        Object perObject = constructor.newInstance("张三",20);
        System.out.println(perObject);

        System.out.println("-------------------------------");

        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
        //创建对象,newInstance简化创建
        Object perObject1 = constructor1.newInstance();
        System.out.println(perObject1);

        System.out.println("-------------------------------");
        Object o = personClass.newInstance();
        System.out.println(o);
    }
}
	}

Method:方法对象
  *执行方法
*object invoke(Object object,Object... ages)
 *获取方法名称
*String getName:获取方法名

实体类中多了两个方法:一个代参,一个不带参,其余的与上述的实体类一致:

    public  void eat1(){
        System.out.println("吃的方法@!");
    }


    public  void eat(String name){
        System.out.println("我是吃的有参的方法!");
    }
package com.haijiao12138.demo.spring.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author: haijiao12138
 * @ClassName: RefulectDemo1
 * @description: TODO
 * @date: 2021/8/15 2:07
 *
 */
public class RefulectDemo1 {
    /**
     *1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
     *2.类名.class:通过类名的class获取
     *3.对象.getClass(): getClass()方法在object类当中定义着
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws Exception {
        //0.获取Person的class对象
        Class personClass = Person.class;

        //获取指定名称的方法,方法无参
        Method eat_method = personClass.getMethod("eat1");
        //执行方法
        Person person =new Person();
        eat_method.invoke(person);

        //获取指定名称的方法,方法有参
        Method eat_method1 = personClass.getMethod("eat",String.class);
        //执行方法
        eat_method1.invoke(person,"饭");



        //获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            //获取方法的名称
            String name = method.getName();
            System.out.println(name);
        }
    }
}

Java Bean利用反射示例:

Bean

package com.haijiao12138.demo.spring.reflection1;


/**
 * @author: haijiao12138
 * @ClassName: Student
 * @description: TODO
 * @date: 2021/8/15 2:51
 *
 */
public class Student {
    private String name;
    private int age;
    private String address;

    public Student(String name,int age,String address) {
        this.address = address;
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}
package com.haijiao12138.demo.spring.reflection1;


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

/**
 * @author: haijiao12138
 * @ClassName: CommonReflect
 * @description: TODO
 * @date: 2021/8/15 2:52
 *
 */
public class CommonReflect {
    //获取该类的名称
    public static void getClassName(Object object) {
        //Class studentClass = Student.class;
        //String name = studentClass.getName().;
        String className = object.getClass().getSimpleName();
        System.out.println("类的名字是:"+className);
    }

    //获取类的变量名称   不考虑修饰符
    public static void getField(Object object) {
        Field[] fields = object.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println("成员变量的名称为:"+fields[i].getName());
        }
    }

    //获取类的成员方法  所有private的方法
    public static void getMethod(Object object) {
        Method[] methods = object.getClass().getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println("成员方法的名称:"+methods[i].getName());
        }
    }

    //调用该类的成员方法,以get为例
    public static void getAction(Object object) throws Exception {
        //获取到有多少get方法
        Field[] fields = object.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            String fistfont = fieldName.substring(0,1).toUpperCase();
            String methodname = "get"+fistfont+fieldName.substring(1); //get+N+name=getName; getAge  getAddress
            Method method = object.getClass().getMethod(methodname);

            System.out.println("get的输出结果:"+method.invoke(object));

        }

    }


    public static void main(String[] args) throws Exception {
        Object studentObject = Student.class.getConstructor(String.class,int.class,String.class).newInstance("张三",20,"保定");
        getClassName(studentObject);//类名
        getField(studentObject);//成员变量名
        getMethod(studentObject);//成员方法名
        getAction(studentObject);//成员变量的输出结果

    }
}

最后 回顾一下  获取class对象的方式:

 /**
     *  1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
     2.类名.class:通过类名的class获取
     3.对象.getClass():getClass()方法在object类当中定义着
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws Exception {
        // 1.Class.forName("全类名"):
        Class class1 = Class.forName("com.haijiao12138.demo.spring.reflection.Person");
        System.out.println(class1);

        //2.类名.class:通过类名的class获取
        Class class2 = Person.class;
        System.out.println(class2);

        //3.对象.getClass()
        Person person = new Person();
        Class class3 = person.getClass();
        System.out.println(class3);
        System.out.println("----------------------------");
        System.out.println(class1  == class2);
        System.out.println(class1  == class3);
    }

你可能感兴趣的:(Java基础,java反射,反射)