java反射机制

目录

一、什么是反射

 二.Java反射机制中获取Class的三种方式及区别?

 2.1 Class的几种获取方式

通过MyClass.class获取,这里的MyClass指具体类~~

通过Class.forName("类的全局定名")获取,全局定名为包名+类名

通过new MyClass().getClass()获取,这里的MyClass指具体类

2.2 代码演示几种方式的区别:

(1)实体类

(2)测试类

 (3)通过测试,得到结果:

(4)总结


一、什么是反射

        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

例子:

package com.justin.java.lang;

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

/**
 * @program: Jdk1.8 Test
 * @description: 正射、反射简单调用示例
 * @author: JustinQin
 * @create: 2021/8/22 13:23
 * @version: v1.0.0
 **/
public class Student {
    private int id;

    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }

    public static void main(String[] args) throws Exception{
        //一、正射调用过程
        Student student = new Student();
        student.setId(1);
        System.out.println("正射调用过程Student id:" + student.getId());

        //二、反射调用过程
        Class clz = Class.forName("com.justin.java.lang.Student");
        Constructor studentConstructor = clz.getConstructor();
        Object studentObj = studentConstructor.newInstance();
        
        Method setIdMethod = clz.getMethod("setId", int.class);
        setIdMethod.invoke(studentObj, 2);
        Method getIdMethod = clz.getMethod("getId");
        System.out.println("正射调用过程Student id:" + getIdMethod.invoke(studentObj));
    }
}

输出结果:

正射调用过程Student id:1
反射调用过程Student id:2

 二.Java反射机制中获取Class的三种方式及区别?

 2.1 Class的几种获取方式

  • 通过MyClass.class获取,这里的MyClass指具体类~~

    通过类名的属性class获取。

    多用于参数的传递。

  • 通过Class.forName("类的全局定名")获取,全局定名为包名+类名

    将字节码文件加载进内存,返回Class对象。

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

  • 通过new MyClass().getClass()获取,这里的MyClass指具体类

     getClass()方法在Object类中定义着。

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

2.2 代码演示几种方式的区别:

(1)实体类

public class MyClass {
    private static final String staticStr = "Hi";
    private static int staticInt = 2021;
    private String id;

    static {
        System.out.println("静态代码块:staticStr=" + staticStr + ",staticInt=" + staticInt);
    }

    {
        System.out.println("动态代码块~");
    }

    public MyClass() {
        System.out.println("无参构造方法~");
    }

    public MyClass(String id) {
        System.out.println("有参构造方法~");
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "MyClass{" +
                "id='" + id + '\'' +
                '}';
    }
}

(2)测试类

package com.justin.java.lang;

import org.junit.Test;

/**
 * @program: Jdk1.8Test
 * @description: Java反射机制中获取类的Class实例对象的常见三种方式及区别对比
 * @author: JustinQin
 * @create: 2021/8/22 15:04
 * @version: v1.0.0
 **/
public class MyClassTest {

    @Test
    public void test1() {
        System.out.println("一、MyClass.class方式=========");
        Class<?> class1 = MyClass.class;
    }

    @Test
    public void test2() throws ClassNotFoundException {
        System.out.println("二、Class.forName方式=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
    }


    @Test
    public void test3() {
        System.out.println("三、new MyClass().getClass方式=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test12() throws ClassNotFoundException {
        System.out.println("一、MyClass.class方式=========");
        Class<?> class1 = MyClass.class;
        System.out.println("二、Class.forName方式=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
    }

    @Test
    public void test13() {
        System.out.println("一、MyClass.class方式=========");
        Class<?> class1 = MyClass.class;
        System.out.println("三、new MyClass().getClass方式=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test23() throws ClassNotFoundException {
        System.out.println("二、Class.forName方式=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
        System.out.println("三、new MyClass().getClass方式=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test() throws ClassNotFoundException {
        System.out.println("四、三种方式内存地址比较=========");
        Class<?> class1 = MyClass.class;
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
        Class class3 = new MyClass().getClass();
        System.out.println("比较结果=========");
        System.out.println("MyClass.class和Class.forName内存地址比较是否相同:" + (class1 == class2));
        System.out.println("MyClass.class和new MyClass().getClass内存地址比较是否相同:" + (class1 == class3));
        System.out.println("Class.forName和new MyClass().getClass内存地址比较是否相同:" + (class2 == class3));
    }
}

 (3)通过测试,得到结果:

* test1()方法
一、MyClass.class方式=========

*  test2()方法
二、Class.forName方式=========
静态代码块:staticStr=Hi,staticInt=2021

*  test3()方法
三、new MyClass().getClass方式=========
静态代码块:staticStr=Hi,staticInt=2021
动态代码块~
无参构造方法~

*  test12()方法
一、MyClass.class方式=========
二、Class.forName方式=========
静态代码块:staticStr=Hi,staticInt=2021

*  test13()方法
一、MyClass.class方式=========
三、new MyClass().getClass方式=========
静态代码块:staticStr=Hi,staticInt=2021
动态代码块~
无参构造方法~

*  test23()方法
二、Class.forName方式=========
静态代码块:staticStr=Hi,staticInt=2021
三、new MyClass().getClass方式=========
动态代码块~
无参构造方法~

*  test()方法
四、三种方式内存地址比较=========
静态代码块:staticStr=Hi,staticInt=2021
动态代码块~
无参构造方法~
比较结果=========
MyClass.class和Class.forName内存地址比较是否相同:true
MyClass.class和new MyClass().getClass内存地址比较是否相同:true
Class.forName和new MyClass().getClass内存地址比较是否相同:true

(4)总结

  • MyClass.class不会做任何类的初始化工作
  • Class.forName会进行类的静态初始化工作
  • new MyClass().getClass静态初始化和非静态初始化工作都会进行

注意:静态代码块只会被加载一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值