反射

反射: 将类的各个组成部分封装成其它对象,如成员变量封装成Field,构造方法封装成Constructor,成员方法封装成Method
在这里插入图片描述
反射好处:

  • 可以在运行阶段操作这些对象
  • 可以代码解耦,提高程序的可扩展性

获取Class类对象的三种方式:

  • Class.forName(“类的全类名”)
  • 类名.class
  • 对象.getClass()

Person类

package codewen.reflect;

/**
 * @author codewen
 */
public class Person {

    public String a1;
    public String a2;
    protected int b;
    int c;
    private int d;

    public Person() {
    }

    public Person(String a1, String a2) {
        this.a1 = a1;
        this.a2 = a2;
    }

    @Override
    public String toString() {
        return "Person{" +
                "a1='" + a1 + '\'' +
                ", a2='" + a2 + '\'' +
                ", b=" + b +
                ", c=" + c +
                ", d=" + d +
                '}';
    }

    public void eat() {
        System.out.println("吃....");
    }
    
    public void eat(String s1, String s2) {
        System.out.println("吃"+s1+"和"+s2);
    }
}

GetClass类

package codewen.reflect;

/**
 *
 * @author codewen
 */
public class GetClass {

    public static void main(String[] args) throws Exception {
        //1.Class.forName("类的全类名")
        Class cls1 = Class.forName("codewen.reflect.Person");
        System.out.println(cls1);
        //2.类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3.对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);

        //============================
        System.out.println("============================");
        System.out.println(cls1==cls2); //true
        System.out.println(cls1==cls3); //true
        System.out.println(cls2==cls3); //true
    }
}

结论: 通过比较三种不同方式获得的Class对象,可以发现他们获取的对象都是同一个,所以,相同字节码文件的Class对象只有一个!

获取Field对象:
在这里插入图片描述

package codewen.reflect;

import java.lang.reflect.Field;

/**
 * 获取Field对象
 * @author codewen
 */
public class GetFields {

    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class personClass = Person.class;
        //getField(String name):获取指定名字的Field对象(只能是公共的)
        System.out.println("===========getField================");
        Field f1 = personClass.getField("a1");
        System.out.println(f1);
        //getFields():获取所有的Field对象(只能是公共的)
        System.out.println("===========getFields================");
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //getDeclaredField(String name):获取指定名字的Filed对象(可以是任意权限的)
        System.out.println("===========getDeclaredField================");
        Field f2 = personClass.getDeclaredField("b");
        Field f3 = personClass.getDeclaredField("d");
        System.out.println(f2);
        System.out.println(f3);
        //getDeclaredFields():获取所有的Filed对象(可以是任意权限的)
        System.out.println("===========getDeclaredFields================");
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        //操作属性
        //getDeclaredField获取的Field对象操作属性只能操作除private修饰的
        //要想操作private修饰的,需要用暴力反射setAccessible(true)来忽略权限修饰符的安全检查
        System.out.println("=========操作属性================");
        Person p = new Person();
        Field c = personClass.getDeclaredField("c");
        c.set(p, 1);
        System.out.println(c.get(p));
        
        Field d = personClass.getDeclaredField("d");
        //暴力反射 用来忽略权限修饰符的安全检查
        d.setAccessible(true);
        d.set(p, 2);
        System.out.println(d.get(p));
    }
}

获取Constructor对象:
在这里插入图片描述

package codewen.reflect;

import java.lang.reflect.Constructor;

/**
 * 获取Constructor对象
 * @author codewen
 */
public class GetConstructors {

    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class personClass = Person.class;
        //getConstructor(类<?>... parameterTypes):获取指定名字的Constructor对象(只能是公共的)
        //参数是不定长参数类型(构造器的参数类型,可以有也可以没有)
        System.out.println("===========getConstructor================");
        Constructor con1 = personClass.getConstructor(); //无参构造
        Constructor con2 = personClass.getConstructor(String.class, String.class); //有参构造
        System.out.println(con1);
        System.out.println(con2);

        //getConstructors():获取所有的Constructor对象(只能是公共的)
        System.out.println("===========getConstructors================");
        Constructor[] constructors = personClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        //getDeclaredConstructor(类<?>... parameterTypes):获取指定名字的Constructor对象(可以是任意权限的)
        //要想操作private修饰的,需要用暴力反射来忽略权限修饰符的安全检查
        //使用与上面类似,不同之处为权限不同
        System.out.println("===========getDeclaredConstructor================");

        //getDeclaredConstructors():获取所有的Constructor对象(可以是任意权限的)
        //要想操作private修饰的,需要用暴力反射来忽略权限修饰符的安全检查
        //使用与上面类似,不同之处为权限不同
        System.out.println("===========getDeclaredConstructors================");

        //创建对象
        System.out.println("============Constructor对象创建对象=================");
        //对于无参
        Object o1 = con1.newInstance();
        System.out.println(o1);
        //对于有参(参数是构造方法所需的参数)
        Object o2 = con2.newInstance("张三", "李四");
        System.out.println(o2);
        //无参形式可以简化
        Object o3 = personClass.newInstance();
        System.out.println(o3);
    }
}

获取Method对象:
在这里插入图片描述

package codewen.reflect;

import java.lang.reflect.Method;

/**
 * 获取Method对象
 * @author codewen
 */
public class GetMethods {

    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class personClass = Person.class;
        //getMethod(String name, 类<?>... parameterTypes):获取指定名字的Method对象(只能是公共的)
        System.out.println("===========getMethod================");

        //getMethods():获取所有的Method对象(只能是公共的)
        System.out.println("===========getMethods================");

        //getDeclaredMethod(String name, 类<?>... parameterTypes):获取指定名字的Method对象(可以是任意权限的)
        //第一个参数是方法名,第二个参数是不定长参数类型(方法所需要的参数类型)
        System.out.println("===========getDeclaredMethod================");
        Person p = new Person();

        //调用方法invoke(Object obj, Object... args)
        //第一个参数是对象,第二个参数是方法所需的参数
        //获取无参的Method对象
        Method m1 = personClass.getDeclaredMethod("eat");
        //调用无参的方法
        Object invoke1 = m1.invoke(p);
        //获取有参的Method对象
        Method m2 = personClass.getDeclaredMethod("eat", String.class, String.class);
        Object invoke2 = m2.invoke(p, "饭", "菜");

        //getDeclaredMethods():获取所有的Method对象(可以是任意权限的)
        System.out.println("===========getDeclaredMethods================");

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

codewen77

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

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

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

打赏作者

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

抵扣说明:

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

余额充值