JAVA单排日记-2020/2/5-Junit-反射

一、反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

反射就是把Java类中的各种成分映射成一个个的Java对象。
在这里插入图片描述

二、反射的理解

反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释。

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

如:

Phone phone = new Phone(); //直接初始化,「正射」
phone.setPrice(4);

上面这样子进行类对象的初始化,我们可以理解为「正」。

而反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。

这时候,我们使用 JDK 提供的反射 API 进行反射调用:

Class clz = Class.forName("com.xxp.reflect.Phone");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);

上面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Phone),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.xxp.reflect.Phone)。

所以说什么是反射?反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

三、反射的常用API

3.1获取反射中的Class对象的三种方式:
  1. Class.forName("类全名")
    Source源代码阶段,将字节码文件加载进内存,返回Class对象。当知道某类的全路径名时,可以使用此静态方法获取 Class 类对象。
    多用于配置文件,将类名定义在配置文件中。读取文件,加载类
Class c1 = Class.forName(“java.lang.String”);
  1. 类名.class
    Class类对象阶段,字节码已经加载到内存中,这种方法只适合在编译前就知道操作的 Class。
    多用于参数的传递
Class c2 = String.class;
  1. 对象.getClass()
    Runtime运行阶段,对象已知,通过对象调用 getClass() 方法来获取
    多用于对象的获取字节码的方式。
String str = new String("Hello");
Class c3 = str.getClass();

使用:
创建Person对象

package junit.reflects;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    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;
    }

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

主程序:

package junit.reflects;

public class Demo {
    public static void main(String[] args) throws Exception {
        /*
        1.Class.forName("类全名")
        2.类名.class
        3.对象.getClass()
        */

        //1.Class.forName("类全名")
        Class c1 = Class.forName("junit.reflects.Person");
        System.out.println(c1);
        //2.类名.class
        Class c2 = Person.class;
        System.out.println(c2);
        //3.对象.getClass()
        Person person = new Person();
        Class c3 = person.getClass();
        System.out.println(c3);
    }
}

在这里插入图片描述

  • 需要注意的是:
    一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1、c2和c3进行 equals 比较,发现都是true。

3.2 Class对象的功能:通过反射获取类属性、方法、构造器

  • 获取功能
  1. 获取成员变量们
Field[] getFields() 获取所有public修饰的成员变量
Field getField(String name) 获取指定名称的public修饰的成员变量
Field[] getDeclareFields() 获取所有的成员变量
Field getDeclaredField(String name) 获取指定的成员变量

具体使用:
创建DemoPersion对象

package junit.reflects;

public class DemoPerson {
    private String name01;
    public String name02;
    String name03;
    protected String name04;
    public String name05;

    public DemoPerson() {
    }

    public DemoPerson(String name01, String name02, String name03, String name04, String name05) {
        this.name01 = name01;
        this.name02 = name02;
        this.name03 = name03;
        this.name04 = name04;
        this.name05 = name05;
    }

    public String getName01() {
        return name01;
    }

    public void setName01(String name01) {
        this.name01 = name01;
    }

    public String getName02() {
        return name02;
    }

    public void setName02(String name02) {
        this.name02 = name02;
    }

    public String getName03() {
        return name03;
    }

    public void setName03(String name03) {
        this.name03 = name03;
    }

    public String getName04() {
        return name04;
    }

    public void setName04(String name04) {
        this.name04 = name04;
    }

    public String getName05() {
        return name05;
    }

    public void setName05(String name05) {
        this.name05 = name05;
    }

    @Override
    public String toString() {
        return "DemoPerson{" +
                "name01='" + name01 + '\'' +
                ", name02='" + name02 + '\'' +
                ", name03='" + name03 + '\'' +
                ", name04='" + name04 + '\'' +
                ", name05='" + name05 + '\'' +
                '}';
    }
}

其中的成员变量:

private String name01;
public String name02;
String name03;
protected String name04;
public String name05;

创建主程序获取DemoPersion的成员变量

package junit.reflects;

import java.lang.reflect.Field;
import java.util.stream.Stream;

public class Demo03 {
    public static void main(String[] args) throws Exception {
        //1.创建Class类对象
        Class c1 =DemoPerson.class;

        //2.通过Class对象获取DemoPerson类的成员变量
        //getFields()获取所有public修饰的成员变量 name02 name05
        Field[] s1 = c1.getFields();
        //getField()获取指定public修饰的成员变量 name05
        Field s2 = c1.getField("name05");
        //getDeclareFields()获取所有成员变量 name01 name02 name03 name04 name05
        Field[] s3 = c1.getDeclaredFields();
        //getDeclareField()获取指定成员变量 name04
        Field s4 = c1.getDeclaredField("name04");

        Stream.of(s1).forEach(System.out::println);
        System.out.println("===========================");
        System.out.println(s2);
        System.out.println("===========================");
        Stream.of(s3).forEach(System.out::println);
        System.out.println("===========================");
        System.out.println(s4);
    }
}

在这里插入图片描述
2. 获取构造方法们

Constructor[] getConstructors();//无参构造
Constructor[] getConstructors(参数1类型.class,参数2类型.class...);//含参构造
Constructor getConstructor();
Constructor getConstructor(参数1类型.class,参数2类型.class...);
Constructor[] getDeclaredConstructors();
Constructor[] getDeclaredConstructors(参数1类型.class,参数2类型.class...);
Constructor getDeclaredConstructor();
Constructor getDeclaredConstructor(参数1类型.class,参数2类型.class...);
  1. 获取成员方法们
Method[] m3 = c1.getMethods();
Method m4 = c1.getMethod(String "方法名",方法参数1类型.class,方法参数2类型.class...);
Method[] m3 = c1.getDeclaredMethods();
Method m4 = c1.getDeclaredMethod(String "方法名",方法参数1类型.class,方法参数2类型.class...);
  1. 获取全类名
Srting getName();
3.3 对获取到的构造方法,成员变量,成员方法的使用
  • 构造方法
  • 创建对象01:构造方法.newInstance
package junit.reflects;

import java.lang.reflect.Constructor;

public class Demo02 {
    public static void main(String[] args) throws Exception {
    	//创建Class对象
        Class c1 = DemoPerson.class;
		//创建含参构造
        Constructor con01 = c1.getConstructor(String.class, String.class, String.class, String.class, String.class);
        //使用newInstance创建对象,添加参数
        Object obj = con01.newInstance("1号","2号","3号","4号","5号");

        System.out.println(obj);
    }
}

在这里插入图片描述

  • 创建对象02:直接class类名.getDeclaredConstructor().newInstance
  • 创建对象03:直接class类名.newInstance(已过时)
  • 成员变量
  • 获取成员变量的值 成员变量.get(类)
  • 设置成员变量的值 成员变量.set(类,值)
  • 暴力反射(修改带修饰符保护的成员)成员变量.setAccessible(true)

成员变量:

private String name01;
public String name02;
String name03;
protected String name04;
public String name05;

主程序:

package junit.reflects;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.stream.Stream;

public class Demo03 {
    public static void main(String[] args) throws Exception {
        //1.创建Class类对象
        Class c1 = DemoPerson.class;
        //2.通过Class对象获取DemoPerson类的成员变量

        //getField()获取指定public修饰的成员变量 name05
        Field s1 = c1.getField("name05");
        //getDeclareField()获取指定成员变量 name04
        Field s2 = c1.getDeclaredField("name04");

        //创建构造方法
        Constructor con = c1.getConstructor();
        Object obj = con.newInstance();

        //使用get与set获取和设置成员变量的值
        s1.set(obj,"5号成员");
        System.out.println(s1);
        System.out.println(s1.get(obj));

        s2.setAccessible(true);//protected保护的成员变量,使用暴力反射
        s2.set(obj,"4号成员");
        System.out.println(s2);
        System.out.println(s2.get(obj));
    }
}

在这里插入图片描述

  • 成员方法
  • 执行方法 :获取的成员方法.invoke(类,成员方法参数1,成员方法参数2....)

类中的成员方法截取:

public void method01(String name,int age){
    System.out.println("姓名:"+name+".年龄:"+age);
}

主程序:

package junit.reflects;

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

public class Demo01 {
    public static void main(String[] args) throws Exception {
        Class c1 = DemoPerson.class;

        Method m1 = c1.getMethod("method01", String.class, int.class);

        Constructor con = c1.getConstructor();
        Object obj = con.newInstance();

        m1.invoke(obj,"张三",12);
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值