反射

反射:框架设计的灵魂

框架:半成品软件。可以在框架的基础上进行软件开发,简化
反射:将类的各个组成部分封装为其他对象
好处:

  1. 可以在程序运行过程中,操作这些对象。
  2. 可以解耦,提高程序的可扩展性。
    java类与对象
    反射机制——将类的组成部分封装为对象

获取Class对象的方式

Class.forName(“全类名”)

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

类名.class

  • 多用于参数的传递

对象.getClass()

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

测试类Person

package cn.itcast.domain;

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 cn.itcast.reflect;

import cn.itcast.domain.Person;

public class ReflectDemo1 {


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

        //1.Class.forName("全类名")
        Class cls1 = Class.forName("cn.itcast.domain.Person");
        System.out.println(cls1);
        //2. 类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3. 对象.getClass() 对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);
    }
}

运行结果

class cn.itcast.domain.Person
class cn.itcast.domain.Person
class cn.itcast.domain.Person

tips: 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

Class对象功能:

获取功能:

获取成员变量

  • Field[] getFields() :获取所有public修饰的成员变量
  • Field getField(String name) 获取指定名称的 public修饰的成员变量
  • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name) 获取指定名称的成员变量,不考虑修饰符

首先建立Person类(其中用到了四种权限的成员变量进行观察)

package cn.itcast.domain;

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

    public String a;
    protected String b;
    String c;
    private String d;

    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 +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
}

分别对四种方法进行测试:在主方法所在类建立

 Class personClass = Person.class;
  1. 进行第一个方法getFields()测试
//1.Field[] getFields():获取public成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("==================");

输出打印为:

public java.lang.String cn.itcast.domain.Person.a

只获取到了a(public)成员变量

  1. 进行第二个方法getField(String name)测试:能对a(public)成员变量的值进行修改
    用变量a接收Class对象所表示的公共成员变量a的字段:

	//2.Field getField(String name):获取public指定成员变量
	Field a=personClass.getField("a");

获取公共变量a的值:

		Person p=new Person();
		Object value=a.get(p);
		System.out.println(value);

输出打印为:

null

现在进行值的修改:

        a.set(p,"zzz");
        System.out.println(p);
        System.out.println("==================");

输出打印为:

Person{name=‘null’, age=0, a=‘zzz’, b=‘null’, c=‘null’, d=‘null’}
==================

  1. 进行第三个方法getDeclaredFields()测试:获取到了所有成员变量的值
        //3.Field[] getDeclaredFields():获取所有成员变量
        Field[] declaredFields=personClass.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println(declaredField);
        }
        System.out.println("==================");

输出打印为:

private java.lang.String cn.itcast.domain.Person.name
private int cn.itcast.domain.Person.age
public java.lang.String cn.itcast.domain.Person.a
protected java.lang.String cn.itcast.domain.Person.b
java.lang.String cn.itcast.domain.Person.c
private java.lang.String cn.itcast.domain.Person.d
==================

  1. 进行第四个方法getDeclaredField(String name)测试
    用变量d接收Class对象所表示的公共成员变量d的字段
        //4.Field getDeclaredField(String name)
        Field d=personClass.getDeclaredField("d");

私有变量不能直接访问,暴力反射

        //私有变量不能直接访问,需要增加一步
        d.setAccessible(true);//暴力反射

        Object value2=d.get(p);
        System.out.println(value2);
        d.set(p,"xxx");
        System.out.println(p);

输出打印为:

Person{name=‘null’, age=0, a=‘zzz’, b=‘null’, c=‘null’, d=‘xxx’}

全部源码

package cn.itcast.reflect;

import cn.itcast.domain.Person;

import java.lang.reflect.Field;

public class ReflectDemo2 {

    /**
     * Class对象功能:
     * 获取功能:
     * 1. 获取成员变量们
     * Field[] getFields()
     * Field getField(String name)
     * <p>
     * Field[] getDeclaredFields()
     * Field getDeclaredField(String name)
     * 2. 获取构造方法们
     * Constructor<?>[] getConstructors()
     * Constructor<T> getConstructor(类<?>... parameterTypes)
     * <p>
     * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     * Constructor<?>[] getDeclaredConstructors()
     * 3. 获取成员方法们:
     * Method[] getMethods()
     * Method getMethod(String name, 类<?>... parameterTypes)
     * <p>
     * Method[] getDeclaredMethods()
     * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
     * <p>
     * 4. 获取类名
     * String getName()
     */

    public static void main(String[] args) throws Exception {

        //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):获取public指定成员变量
        Field a = personClass.getField("a");
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        a.set(p, "zzz");
        System.out.println(p);
        System.out.println("==================");

        //3.Field[] getDeclaredFields():获取所有成员变量
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("==================");

        //4.Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("d");
        //私有变量不能直接访问,需要增加一步
        d.setAccessible(true);//暴力反射

        Object value2 = d.get(p);
        System.out.println(value2);
        d.set(p, "xxx");
        System.out.println(p);

    }
}

运行结果

public java.lang.String cn.itcast.domain.Person.a
==================
null
Person{name=‘null’, age=0, a=‘zzz’, b=‘null’, c=‘null’, d=‘null’}
==================
private java.lang.String cn.itcast.domain.Person.name
private int cn.itcast.domain.Person.age
public java.lang.String cn.itcast.domain.Person.a
protected java.lang.String cn.itcast.domain.Person.b
java.lang.String cn.itcast.domain.Person.c
private java.lang.String cn.itcast.domain.Person.d
==================
Person{name=‘null’, age=0, a=‘zzz’, b=‘null’, c=‘null’, d=‘xxx’}

获取构造方法

  • Constructor<?>[] getConstructors()
  • Constructor<T> getConstructor(类<?>... parameterTypes)
  • Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
  • Constructor<?>[] getDeclaredConstructors()
package cn.itcast.reflect;

import cn.itcast.domain.Person;

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

public class ReflectDemo3 {

    /**
     * Class对象功能:
     * 获取功能:
     * 1. 获取成员变量们
     * Field[] getFields()
     * Field getField(String name)
     * <p>
     * Field[] getDeclaredFields()
     * Field getDeclaredField(String name)
     * 2. 获取构造方法们
     * Constructor<?>[] getConstructors()
     * Constructor<T> getConstructor(类<?>... parameterTypes)
     * <p>
     * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     * Constructor<?>[] getDeclaredConstructors()
     * 3. 获取成员方法们:
     * Method[] getMethods()
     * Method getMethod(String name, 类<?>... parameterTypes)
     * <p>
     * Method[] getDeclaredMethods()
     * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
     * <p>
     * 4. 获取类名
     * String getName()
     */

    public static void main(String[] args) throws Exception {

        //0.获取Person的Class对象
        Class personClass = Person.class;
        /*
            2. 获取构造方法们
                 * Constructor<?>[] getConstructors()
                 * Constructor<T> getConstructor(类<?>... parameterTypes)

                 * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
                 * Constructor<?>[] getDeclaredConstructors()
         */

        //Constructor<T> getConstructor(类<?>... parameterTypes)
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);

        //利用构造器创建对象(含空参构造,也含带参构造)class->constructor->对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person);
        //利用class构造(默认空参构造) class->对象
        Object person1 = personClass.newInstance();
        System.out.println(person1);
    }
}

运行结果

public cn.itcast.domain.Person(java.lang.String,int)
Person{name=‘张三’, age=23, a=‘null’, b=‘null’, c=‘null’, d=‘null’}
Person{name=‘null’, age=0, a=‘null’, b=‘null’, c=‘null’, d=‘null’}

获取成员方法:

  • Method[] getMethods()
  • Method getMethod(String name, 类<?>... parameterTypes)
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, 类<?>... parameterTypes)
package cn.itcast.reflect;

import cn.itcast.domain.Person;

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

public class ReflectDemo4 {

    /**
     * Class对象功能:
     * 获取功能:
     * 1. 获取成员变量们
     * Field[] getFields()
     * Field getField(String name)
     * <p>
     * Field[] getDeclaredFields()
     * Field getDeclaredField(String name)
     * 2. 获取构造方法们
     * Constructor<?>[] getConstructors()
     * Constructor<T> getConstructor(类<?>... parameterTypes)
     * <p>
     * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     * Constructor<?>[] getDeclaredConstructors()
     * 3. 获取成员方法们:
     * Method[] getMethods()
     * Method getMethod(String name, 类<?>... parameterTypes)
     * <p>
     * Method[] getDeclaredMethods()
     * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
     * <p>
     * 4. 获取类名
     * String getName()
     */

    public static void main(String[] args) throws Exception {

        //0.获取Person的Class对象
        Class personClass = Person.class;
        /*
          3. 获取成员方法们:
             * Method[] getMethods()
             * Method getMethod(String name, 类<?>... parameterTypes)

             * Method[] getDeclaredMethods()
             * Method getDeclaredMethod(String name, 类<?>... parameterTypes)
         */
        //1. Method[] getMethods():获取所有的公共方法
        Method[] methods = personClass.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }

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

        //2. Method getMethod(String name, 类<?>... parameterTypes):获取指定的公共方法
        Method method = personClass.getMethod("eat");
        System.out.println(method);//打印方法
        Person person = new Person();
        method.invoke(person);//执行方法

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

        //3. Method[] getDeclaredMethods():获取所有的方法
        Method[] methods1 = personClass.getDeclaredMethods();
        for (Method m : methods1) {
            System.out.println(m);
        }

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

        //4. Method getDeclaredMethod(String name, 类<?>... parameterTypes):获取指定的方法

    }
}

运行结果

public java.lang.String cn.itcast.domain.Person.toString()
public java.lang.String cn.itcast.domain.Person.getName()
public void cn.itcast.domain.Person.setName(java.lang.String)
public int cn.itcast.domain.Person.getAge()
public void cn.itcast.domain.Person.eat()
public void cn.itcast.domain.Person.setAge(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
==================
public void cn.itcast.domain.Person.eat()
eat…
==================
public java.lang.String cn.itcast.domain.Person.toString()
public java.lang.String cn.itcast.domain.Person.getName()
public void cn.itcast.domain.Person.setName(java.lang.String)
public int cn.itcast.domain.Person.getAge()
public void cn.itcast.domain.Person.eat()
public void cn.itcast.domain.Person.setAge(int)
==================

获取类名

  • String getName()

练习:

  • 案例:
  • 需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
  • 实现:
    1. 配置文件
    2. 反射
  • 步骤:
  1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中

  2. 在程序中加载读取配置文件

  3. 使用反射技术来加载类文件进内存

  4. 创建对象

  5. 执行方法

package cn.itcast.reflect;

import cn.itcast.domain.Person;
import cn.itcast.domain.Student;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 可以创建任意类的对象,可以执行任意方法
 * 框架类
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
//        Person p=new Person();
//        p.eat();
//        Student s=new Student();
//        s.sleep();
        //加载配置文件
        Properties pro = new Properties();
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
        pro.load(resourceAsStream);

        //获取配置文件中的数据,包括类的Class和method
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //加载该类进内存
        Class cls = Class.forName(className);

        //创建类对象
        Object obj = cls.newInstance();

        //获取方法对象
        Method method = cls.getMethod(methodName);

        //利用创建好的类对象和方法对象,来运行方法
        method.invoke(obj);

    }
}

配置文件1:

配置文件
运行结果

sleep…

配置文件2:
配置文件
运行结果

eat…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绕球飞行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值