第33天学习打卡(反射)

反射概述

反射

在程序运行过程中分析类的一种能力。

反射能做什么:

分析类

加载并初始化一个类,查看类的所有属性和方法

查看并使用对象

查看一个对象的所有属性和方法使用对象的任意属性和方法

反射的应用场景

构建通用工具

搭建具有高度灵活性和扩展性的系统框架

类加载器(ClassLoader)

负责将类的字节码文件(.class文件)加载到内存中,并生成对应的Class对象。

Class对象

java.lang.Class类的对象,也加字节码文件对象,每个Class对象对应一个字节码文件。

image-20210210074514216

类的加载时机

创建类的实例
Student stu = new Student();

一个类的字节码文件只会被加载一次

访问类的静态成员
Calendar.getInstance();

先加载Calendar的字节码文件到内存

初始化类的子类
class User extends Person{
    
    }
User user = new Use();//先加载父类Person
反射方式创建类的Class对象
Class clazz = Class.forName("类的正名");
    正名: 包名 + 类名,例如:cn.itcast.demo01.Student

获取Class对象的三种方式

Object类的getClass()方法:

Class clazz = 对象名.getClass();

类的静态属性:

Class clazz = 类名.class;

Class类的静态方法:

Class clazz = Class.forName("类的正名");
正名:包类路径名,如:cn.itcast.bean.Student
package cn.itcast.demo29;
/**
 * 获取Class对象(字节码文件对象)的三种方式
 *    1.Object类的getClass()方法
 *            Class clazz = 对象名.getClass();
 *    2.类的静态属性
 *            Class clazz = 类名.class
 *    3.Class类的静态方法
 *            Class clazz = Class.forName("类的正名");
 *            正名:包名 + 类名
 *
 *    注意:一个源文件(.java文件)对应一个字节码文件对象(.class)
 *
 */

public class ReflectDemo01 {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        //需求:获取Class对象
        //方式一:
        Student stu = new Student();
        Class clazz1 = stu.getClass();


        //方式二:
        Class clazz2 = Student.class;

        //方式三
        Class clazz3 = Class.forName("cn.itcast.demo29.Student");
        System.out.println(clazz1 == clazz2);//输出结果为true
        System.out.println(clazz2 == clazz3);//输出结果为true



    }
}

反射方式获取构造方法并使用

Constructor对象

构造器对象,属于java.base模块,java.lang.reflect包

通过Class对象获取构造器对象

getConstructor(Class<?>...parameterTypes)
               返回一个Constructor对象,仅公共构造参数
               Class<?>...:可变参数,代表Class类型的数组
                   ?:通配符,代表不确定的任意类型
                       
getDeclaredConstructor(Class<?>...parameterTypes)
                       返回一个Constructor对象,可获取私有构造函数
getConstructors()
                        返回此类所有(不含私有)构造函数的数组

Constructor的常用方法

String getName()
          返回构造函数
T newInstance(Object...initargs)
           使用此构造函数和指定参数创建并初始化对象

image-20210210094303956

package cn.itcast.demo30;

import java.lang.reflect.Constructor;

/**
 *Class类
 *     成员方法:
 *           public Constructor getConstructor(Class...params);
 *                    根据参数列表,获取对应的构造器对象(仅限公共构造函数)
 *           public Constructor getDeclaredConstructor(Class...params);
 *                    根据参数列表,获取对应的构造器对象(包含私有构造函数)
 *           public Constructors[] getConstructors();获取此类所有的构造函数(不包含私有)
 *
 *   *Constructor类: 构造器类
 *          概述:属于java.base模块下的java.lang.reflect包下的类
 *
 *          成员方法:
 *          public String getName();  获取构造函数名
 *          public T newInstances(Object...params); 根据此构造函数和指定参数创建对象
 */

public class ReflectDemo01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //需求:通过反射的方式创建:Student类型的对象
        //1.获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo30.Student");

        //2.根据第一步获取到的字节码文件对象,获取指定的构造器对象
        //2.1获取公共的无参构造
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);
        //2.2获取公共的有参构造

        Constructor con2 = clazz.getConstructor(String.class);
        System.out.println(con2);

        //2.3获取私有的有参构造
        Constructor con3 = clazz.getDeclaredConstructor(int.class);
        System.out.println(con3);

        //2.4获取Student类的所有公共的构造函数
        System.out.println("=====================");
        Constructor[] cons = clazz.getConstructors();

        //遍历数组
        for(Constructor con : cons){
    
    
            System.out.println(con);
        }

        //3.根据构造器对象和参数,创建对应的Student对象
        //4.打印结果

    }
}

输出结果:

D:\Java\JDK8\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA
public cn.itcast.demo30.Student()
public cn.itcast.demo30.Student(java.lang.String)

private cn.itcast.demo30.Student(int)

public cn.itcast.demo30.Student()
public cn.itcast.demo30.Student(java.lang.String)

Process finished with exit code 0

package cn.itcast.demo30;

import java.lang.reflect.Constructor;

/**
 *Class类
 *     成员方法:
 *           public Constructor getConstructor(Class...params);
 *                    根据参数列表,获取对应的构造器对象(仅限公共构造函数)
 *           public Constructor getDeclaredConstructor(Class...params);
 *                    根据参数列表,获取对应的构造器对象(包含私有构造函数)
 *           public Constructors[] getConstructors();获取此类所有的构造函数(不包含私有)
 *
 *   *Constructor类: 构造器类
 *          概述:属于java.base模块下的java.lang.reflect包下的类
 *
 *          成员方法:
 *          public String getName();  获取构造函数名
 *          public T newInstances(Object...params); 根据此构造函数和指定参数创建对象
 */

public class ReflectDemo01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //需求:通过反射的方式创建:Student类型的对象
        //1.获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo30.Student");

        //2.根据第一步获取到的字节码文件对象,获取指定的构造器对象
        /*  //2.1获取公共的无参构造
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);
        //2.2获取公共的有参构造

        Constructor con2 = clazz.getConstructor(String.class);
        System.out.println(con2);

        //2.3获取私有的有参构造
        Constructor con3 = clazz.getDeclaredConstructor(int.class);
        System.out.println(con3);

        //2.4获取Student类的所有公共的构造函数
        System.out.println("=====================");
        Constructor[] cons = clazz.getConstructors();

        //遍历数组
        for(Constructor con : cons){
            System.out.println(con);
        }*/
        //2.2获取公共的有参构造

        Constructor con2 = clazz.getConstructor(String.class);
        System.out.println(con2);
        //获取构造器的名字,看看他是哪个类的构造
        String name = con2.getName();
        System.out.println(name);

        //3.根据构造器对象和参数,创建对应的Student对象
        Student stu = (Student) con2.newInstance("张三");
        System.out.println(stu);
        //4.打印结果

    }
}

package cn.itcast.demo30;
//学生类
public class Student {
    
    
    //公共的无参构造
    public Student(){
    
    

    }
    //公共的带参构造
    public Student(String name){
    
    
        System.out.println("您录入的name的值是: " + name);

    }
    //私有的带参构造
    private  Student(int age){
    
    
        System.out.println("您录入的age的值是: " + age);
    }
}

输出结果:

public cn.itcast.demo30.Student(java.lang.String)
cn.itcast.demo30.Student
您录入的name的值是: 张三
cn.itcast.demo30.Student@14ae5a5

反射方式获取成员方法并使用

Method对象

方法对象,属于java.base模块,java.lang.reflect包

通过Class对象获取方法

getMethod(String name,Class<?>...parameterTypes)
          返回一个Method对象,仅公共成员方法
          neme:方法名
          parameterTypes:方法的参数列表
getDeclaredMethod(String,Class<?>...)
           返回一个Method对象,可获取私有成员方法
getMethods()
           返回此类所有(不含私有)的方法数组
       

Method的常用方法

String getName()
        返回方法名
Object invoke(Object obj, Object ...args)
        在指定对象上调用此方法,参数为args
        

image-20210210103800216

package cn.itcast.demo31;

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

/**
 *Class类
 *     成员方法:
 *           public Method getMethod(String name,Class...params)
 *           返回一个Method对象,仅公共成员方法
 *           public Method getDeclaredMethod(String,Class...params)
 *           返回一个Method对象,可获取私有成员方法
 *           public Method[] getMethods()返回此类所有(不含私有)方法的数组
 *           
 *
 *   *Method类: 方法类
 *          概述:属于java.base模块下的java.lang.reflect包下的类
 *
 *          成员方法:
 *          public String getName();  获取成员方法名
 *          public Object invoke(Object obj,Object...params); 调用指定方法,obj表示该类的对象,params表示调用该方法所需的参数
 *
 *          public void setAccessible(boolean flag):是否开启暴力反射(true:开启)
 */

public class ReflectDemo01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //需求:通过反射获取Student类中的成员方法并调用
        //1.获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo31.Student");
        //2.获取该类的构造器对象,然后创建Student类的对象
        Constructor con = clazz.getConstructor();
        Student stu = (Student)con.newInstance();
       // System.out.println(stu);

        //3.获取该类的成员方法对象,然后调用此方法
        //3.1调用公共的空参构造
        Method method1 = clazz.getMethod("show1");
        //打印方法对象
        System.out.println(method1);

        //打印方法名
        System.out.println(method1.getName());

        //调用此方法
        method1.invoke(stu);//返回是void类型不需要变量进行接收
        System.out.println("==================");
        //3.2公共的带参方法
        Method method2 = clazz.getMethod("show2", int.class);
        //调用方法
        method2.invoke(stu,100);


        System.out.println("================");
        //3.3调用私有的带参方法
        Method method3 = clazz.getDeclaredMethod("show3", int.class, int.class);
        //开启暴力反射
        method3.setAccessible(true);
        //调用此方法
       int sum = (int) method3.invoke(stu,10,20);
        System.out.println("您录入的两个数的和是: " + sum);
        System.out.println("=====================");

        //3.4获取Student类中的所有的成员方法
        Method[] methods = clazz.getMethods();
        for(Method method : methods){
    
    
            System.out.println(method);
        }



    }
}

package cn.itcast.demo31;

public class Student {
    
    
    //公共的空参方法
    public void show1(){
    
    
        System.out.println("我是公共的空参方法");
    }
    //公共的带参方法
    public void show2(int a){
    
    
        System.out.println("我是公共的带参方法,您传入的值是: " + a);

    }
    //私有的带参方法
    private int show3(int a, int b){
    
    
        System.out.println("我是私有的带参方法");
        return  a + b;
    }
}

反射方式获取成员变量并使用

Filed 对象

域(属性、成员变量)对象,属于java.base模块

java.lang.reflect包

通过Class对象获取属性
getField(String name)
        返回一个Filed对象,仅公共属性
        name:属性名
getDeclaredField(String name)
        返回一个Filed对象,可获取私有属性
getDeclaredFields()
        返回此类所有(含私有)属性的数组
        

Field的常用方法

void set(Object obj,Object value)
         设置obj对象的指定属性值为value
         
void setAccessible(boolean flag)
         将此属性的可访问性设置为指定布尔值

image-20210210114039870

package cn.itcast.demo33;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * Class类
 *    成员方法:
 *         public Filed getField(String name)返回一个Field对象,仅公共成员变量
 *         public Field getField(String name)返回一个Field对象,可获取私有成员变量
 *         public Field[] getDeclaredFields() 返回此类所有(含私有)成员变量的数组
 *
 * Field: 属性类,用来表示所有域(属性, 成员变量)对象的。
 *        概述:属于java.base模块下的java.lang.reflect包下的类
 *
 *    成员方法:
 *    public void setAccessible(boolean flag)   是否开启暴力反射(true :开启)
 *    public void set(Object obj,Object value); 设置obj对象的指定属性值为value
 *
 */


public class ReflectDemo01 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //需求:通过反射获取成员变量并使用
        //1.获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo33.Student");
        //2.通过字节码文件对象获取构造器对象,然后创建学生类对象
        Constructor con = clazz.getConstructor();
        Student stu = (Student)con.newInstance();
        //这行代码是上述两行代码的合并写法
       // Student stu2 = (Student)clazz.getConstructor().newInstance();链式编程:方法返回值还是一个对象的时候还可以在后面.方法
        //3.设置学生对象的各个属性值
        //3.1设置姓名
        Field field1 = clazz.getField("name");
        field1.set(stu,"豆豆");

        //3.2设置年龄
        Field field2 = clazz.getDeclaredField("age");
        //开启暴力反射
        field2.setAccessible(true);
        field2.set(stu,18);

        //4.打印学生对象
        System.out.println(stu);


    }
}

猜你喜欢

转载自blog.csdn.net/doudoutj/article/details/113781106