Java(day18)反射

概念:反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。

常用方法

获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名

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

获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)

获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)

反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法

反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null

反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法

主体代码:

package cn.tedu.reflection;
//学习反射的物料类
public class Student {
    private String name;
    public int age;

    public String getName() {
        return name;
    }

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

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void play(){
        System.out.println("今天大结局,放学后我要写1w行代码");
    }
    public void eat(int n){
        System.out.println("今天要吃"+n+"道好菜");
    }

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

获取字节码对象的3种方式:

package cn.tedu.reflection;

import org.junit.Test;

public class TestReflect {
    @Test
    public void getClazz() throws ClassNotFoundException {
        Class<?> clazz1 = Class.forName("cn.tedu.reflection.Student");
        Class<?> clazz2 = Student.class;
        Class<?> clazz3 = new Student().getClass();
        System.out.println(clazz1);
        System.out.println(clazz2);
        System.out.println(clazz3);

    }
}
运行结果:
class cn.tedu.reflection.Student
class cn.tedu.reflection.Student
class cn.tedu.reflection.Student
package cn.tedu.reflection;

import org.junit.Test;

public class TestReflect {
    @Test
    public void getClazz() throws ClassNotFoundException {

        //通过字节码对象获取student类的资源
        Class<?> clazz1 = Class.forName("cn.tedu.reflection.Student");
        System.out.println(clazz1);
        //获取字节码对象对应的全路径名
        System.out.println(clazz1.getName());
        //获取字节码对象对应的类名
        System.out.println(clazz1.getSimpleName());
        //获取Student类对应的包对象
        System.out.println(clazz1.getPackage());
        //先获取Student类对应的包对象,再通过这个包对象获取包名
        System.out.println(clazz1.getPackage().getName());

    }
}
运行结果:
class cn.tedu.reflection.Student
cn.tedu.reflection.Student
Student
package cn.tedu.reflection
cn.tedu.reflection

通过触发目标类的无参构造和构造函数创建对象

@Test
public void getObject() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
       Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
       Object o = clazz.newInstance();
        System.out.println(o);


        //获取目标类中指定的全参构造函数对象
        Constructor<?> c = clazz.getConstructor(String.class,int.class);
        //创建对象并赋值
        Object o2 = c.newInstance("赵六", 6);
        System.out.println(o2);


    }
运行结果:
Student{name='null', age=0}
Student{name='赵六', age=6}

暴力反射:获取私有属性和方法

package cn.tedu.reflection;
//本类用于暴力反射的物料类
public class Person {
    private String name;
    private int age;
    private void save(int n,String s){
        System.out.println("save方法"+n+s);
    }
    private void update(){
        System.out.println("update方法");
    }

}
package cn.tedu.reflection;

import org.junit.Test;

import java.lang.reflect.Field;

//本类用于测试暴力反射
public class TestReflect2 {
    //通过暴力反射获取与操作属性
    @Test
    public void GetFie2() throws Exception {
        Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
        //获取指定的私有属性,方法参数传入的就是指定的属性的名字
        Field field = clazz.getDeclaredField("name");
        System.out.println(field);
        //通过刚刚获取的属性对象,进一步查看属性的各种信息
        System.out.println(field.getType());
        System.out.println(field.getType().getName());

        //设置属性的值
        //需要指定是哪个对象的name属性设置值,所以创建对象
        Object p1 = clazz.newInstance();
        //暴力反射,需要设置私有私有可见的权限
        field.setAccessible(true);
        //通过字段对象给刚刚创建好的p1设置属性值
        //field.set(o,n);o是指具体给那个对象的属性设置值,n是指具体的值是什么
        field.set(p1,"海绵");
        //field.get(p1);o是指具体查看哪个对象的name属性
        System.out.println(field.get(p1));
    }
//通过暴力反射获取与操作方法
    @Test
    public void getFuntion() throws Exception {
        Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
        //获取指定的私有方法
        //clazz.getDeclaredMethod(n,x,y,z....)n是获取的指定方法的方法名,xyz是指定方法的参数类型
        Method method= clazz.getDeclaredMethod("save", int.class, String.class);

        //暴力反射设置权限
        method.setAccessible(true);
        //创建persion对象
        Object p3 = clazz.newInstance();
        //invoke(o,x,y,z)通过反射执行方法o:是要给哪个对象执行上面获取的save(),xyz是执行save()时需要传入的参数
        method.invoke(p3,999,"感冒灵");

    }
}
运行结果:
private java.lang.String cn.tedu.reflection.Person.name
class java.lang.String
java.lang.String
海绵


save方法999感冒灵

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值