java反射运用基础,超详细

概述

Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,private的只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。


反射运用基础

基础测试类

package com.cy;

import java.util.Objects;

public class Shop {
    public final Integer NUMBER = 10;
    public final String BRAND = "BRAND";
    private String name;
    private Integer price;
    private Integer sales;

    public Shop() {
        System.out.println("-----我是公有无参构造方法-----");
    }

    private Shop(String name, Integer price) {
        System.out.println("-----我是私有有参构造方法-----");
        this.name = name;
        this.price = price;
    }

    public Shop(String name, Integer price, Integer sales) {
        System.out.println("-----我是公有有参构造方法-----");
        this.name = name;
        this.price = price;
        this.sales = sales;
    }

    private void priMethod() {
        System.out.println("-----我是私有方法-----");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Integer getSales() {
        return sales;
    }

    public void setSales(Integer sales) {
        this.sales = sales;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Shop shop = (Shop) o;
        return name.equals(shop.name) &&
                price.equals(shop.price) &&
                sales.equals(shop.sales);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, price, sales);
    }
    
	@Override
    public String toString() {
        return "Shop{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", sales=" + sales +
                '}';
    }
}

获取类对象属性

Class.forName(“类路径”) – 获取类对象
getPackage().getName() – 获取包名
getName() – 获取完整类名
getSimpleName() – 类名,不含包名

测试:

	@Test
    public void test1() throws Exception{
        Class c = Class.forName("com.cy.Shop");
        String packageName = c.getPackage().getName();
        String className = c.getName();
        String simpleName = c.getSimpleName();
        System.out.println("packageName: " + packageName);
        System.out.println("className: " + className);
        System.out.println("simpleName: " + simpleName);
    }

运行结果:
java反射运用基础,超详细

获取成员变量定义信息

getFields() – 获得所有公开的成员变量,包括继承的变量
getDeclaredFields() – 获得本类定义的成员变量,包括私有,不包括继承的变量
getField(变量名) – 获取指定成员变量
getDeclaredField(变量名) – 获得指定本类定义的成员变量

测试:

	@Test
	public void test2() throws Exception{
	    Shop shop = new Shop();
	    Class c = shop.getClass();
	    Field[] fields = c.getFields();
	    for (Field field : fields) {
	        System.out.println(field.toString());
	    }
	    System.out.println("-----------------------------");
	    Field[] declaredFields = c.getDeclaredFields();
	    for (Field field : declaredFields) {
	        System.out.println(field.toString());
	    }
	    System.out.println("-----------------------------");
	    Field field = c.getField("NUMBER");
	    Field declaredField = c.getDeclaredField("name");
	    System.out.println(field.toString());
	    System.out.println(declaredField.toString());
	}

运行结果:
java反射运用基础,超详细

获取方法定义信息

getMethods() – 获得所有可见的方法,包括继承的方法
getDeclaredMethods() – 获得本类定义的方法,包括私有,不包括继承的方法
getMethod(方法名,参数类型列表) – 获得指定可见的方法
getDeclaredMethod(方法名, 参数类型列表) – 获得本类指定的方法,包括私有,不包括继承的方法

测试:

	@Test
    public void test3() throws Exception{
        Class c = Class.forName("com.cy.Shop");
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            System.out.println(method.toString());
        }
        System.out.println("----------------------------");
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.toString());
        }
        System.out.println("----------------------------");
        Method method = c.getMethod("setName", String.class);
        System.out.println(method.toString());
        Method declaredMethod = c.getDeclaredMethod("priMethod");
        System.out.println(declaredMethod.toString());
    }

运行结果:
java反射运用基础,超详细

获取构造方法定义信息

getConstructors() – 获得所有公开的构造方法
getDeclaredConstructors() – 获得所有构造方法,包括私有
getConstructor(参数类型列表) – 获得指定公开的构造方法
getDeclaredConstructor(int.class, String.class) – 获得指定构造方法,包括私有

测试:

	@Test
    public void test4() throws Exception{
        Class c = Class.forName("com.cy.Shop");
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.toString());
        }
        System.out.println("---------------------------------------");
        Constructor[] declaredConstructors = c.getDeclaredConstructors();
        for (Constructor constructor : declaredConstructors) {
            System.out.println(constructor.toString());
        }
        System.out.println("---------------------------------------");
        Constructor constructor = c.getConstructor();
        System.out.println(constructor.toString());
        Constructor declaredConstructor = c.getDeclaredConstructor(String.class, Integer.class);
        System.out.println(declaredConstructor.toString());
    }

反射访问类的属性

反射新建实例

— 新建实例时,执行无参构造
Object obj = 类(Class).newInstance();

— 获取构造方法
Constructor t = 类(Class).getConstructor(参数类型列表);

— 新建实例,并执行该构造方法
Object obj = t.newInstance(参数数据列表);

反射调用成员变量

— 获取变量
Field field = 类(Class).getDeclaredField(变量名);

— 使私有成员允许访问
field.setAccessible(true);

— 反射给变量赋值
field.set(实例, 值);

— 反射访问变量的值
Object v = field.get(实例);

反射调用成员方法

获取方法
Method m = 类(Class).getDeclaredMethod(方法名, 参数类型列表);

使私有方法允许被调用
m.setAccessible(true)

反射让指定的实例来执行该方法
Object returnValue = m.invoke(实例, 参数数据)

测试:

	@Test
    public void test5() throws Exception{
        Class c = Class.forName("com.cy.Shop");
        Constructor declaredConstructor = c.getDeclaredConstructor(String.class, Integer.class);
        // 反射使私有构造方法允许访问
        declaredConstructor.setAccessible(true);
        // 反射调用私有构造方法创建实例
        Shop shop = (Shop)declaredConstructor.newInstance("苹果", 10);
        System.out.println(shop.toString());
        System.out.println("-----------------------------------------");
        Constructor constructor = c.getConstructor();
        // 反射调用公有构造方法创建实例
        Shop shop1 = (Shop)constructor.newInstance();
        System.out.println(shop1.toString());
        System.out.println("-----------------------------------------");
        Field field = c.getDeclaredField("name");
        // 反射使成员变量允许访问
        field.setAccessible(true);
        // 反射给成员变量赋值
        field.set(shop1, "香蕉");
        // 反射访问成员变量
        String name = (String)field.get(shop1);
        System.out.println(shop1.toString());
        System.out.println(name);
        System.out.println("-----------------------------------------");
        Method method = c.getDeclaredMethod("priMethod");
        // 反射使私有方法允许访问
        method.setAccessible(true);
        // 反射指定实例调用该私有方法
        method.invoke(shop1);
    }

运行结果:
java反射运用基础,超详细

上一篇:MySQL数据库分页语句


下一篇:1475. Final Prices With a Special Discount in a Shop