Java Web项目——2.反射基础知识

目录

一、前言

二、获取class对象的三种方式

三、Class对象功能

(1)获取成员变量

(2)获取构造方法

 (3)获取成员方法

(4)获取类名


一、前言

写框架需要用到反射,而用框架不需要。

将字节码文件中的成员变量、构造方法、成员方法通过类加载器ClassLoader封装成一个个的对象。(这一部分并不是特别清晰,先看后面的网课)

二、获取class对象的三种方式

package cn.itcast.reflect;

//获取class对象的三种方式

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

public class PersonTest {
    public static void main(String[] args) throws ClassNotFoundException {

        //1:  Class.forName("全类名")
        //全类名:包名.类名
        Class c1 = Class.forName("cn.itcast.domain.Person");
        //上一行需要处理异常,可以直接通过main函数抛出:ClassNotFoundException
        System.out.println(c1);

        //2:  类名.class
        Class c2 = Person.class;    //这里需要导入Person
        System.out.println(c2);

        //3:  对象名.getClass();
        Person p = new Person();
        Class c3 = p.getClass();
        System.out.println(c3);

        //用==来判断两个对象是否相同(因为==是判断地址)
        System.out.println(c1==c2);//true
        System.out.println(c1==c3);//true


        Class c = Student.class;//需要导入Student
        System.out.println(c==c1);//false

    }
}

三、Class对象功能

代码格式化快捷键:Ctrl+Alt+L

(1)获取成员变量

        Class personClass = Person.class;
        Field[] Fields = personClass.getFields();
        for (Field field : Fields) {
            System.out.println(field);
        }

遍历Person的Class对象(字节码文件对象)中的所有成员变量(需要注意的是,这里只能遍历用public修饰的成员变量)

        //获取Person的Class对象,获取名称为a的成员变量,获取并修改其值
        Field a = personClass.getField("a");
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        //设置值
        a.set(p,"张三");
        System.out.println(p);

a为Person的Class对象中名称为a的成员变量对象,此时,分别获取和设置该成员变量的值,并打印:

 由于a是String对象,所以其初始值为null;重写toString方法后,可以看到a的值被修改为张三。

        //getDeclaredFields方法可以获取Class对象中的所有成员变量(不管是什么修饰符修饰的)
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //获取用private修饰的成员变量d的值
        Field d = personClass.getDeclaredField("d");
        Object value2 = d.get(p);
        System.out.println(value2);

 

getDeclaredFields方法可以获取所有变量(不局限于用public修饰的变量),当获取d变量值时,由于其并不是用public修饰的变量,所以会产生异常(也就是说,declared方法只能获得所有成员变量及用public修饰的变量的值)。若想要获取所有变量的值,则需要加入另一个方法:

        Field d = personClass.getDeclaredField("d");
        d.setAccessible(true);//暴力反射
        Object value2 = d.get(p);
        System.out.println(value2);

此时,我就可以获取用private修饰的d变量的值而产生异常,可见其值为null。 

暴力反射:d.setAccessible(true);        //让调用该方法的变量的值直接被访问(忽视访问修饰符的安全检查)

总结: 加上declared可以帮助获取非public修饰的成员变量,但是想要获取该变量的值,则还需要该变量调用setAccessible(true),从而暴力反射。

(2)获取构造方法

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

        Class personClass = Person.class;

        //获取参数分别为String和int类型的构造方法
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("张三", 23);//用该构造方法创建实例对象
        System.out.println(person);

        /*  以下是黑马老师讲的代码,但是一运行就会显示异常,据说是已经过时?

        //获取无参构造方法,但是这个方法比较麻烦,可以使用方法2
        Constructor constructor1 = personClass.getConstructor();
        Object person1 = constructor.newInstance();//用该构造方法创建实例对象
        System.out.println(person);

        //方法2
        Object person2 = personClass.newInstance();
        System.out.println(person2);
        */
    }

第一个有参构造创建对象的方法可以使用,注释内的无参构造方法不能使用,可能是版本问题。

        Object person1 = personClass.getConstructor().newInstance();
        System.out.println(person1);
        Object person2 = personClass.getConstructor(String.class,int.class).newInstance("李四",25);                     
        System.out.println(person2);

这个方法既可以调用无参构造,也可以调用有参构造,而且形式较为简单,建议以后使用这个,下面是运行截图:

 (3)获取成员方法

获取指定名称的方法:

public static void main(String[] args) throws Exception {
        //获取Person的Class对象,获取对象的所有成员变量,遍历打印
        Class personClass = Person.class;

        //获取无参数的eat方法
        Method method = personClass.getMethod("eat");
        Person p = new Person();
        method.invoke(p);

        //获取有参数的构造方法
        Method method1 = personClass.getMethod("eat", String.class);//  (方法名,参数类型)
        method1.invoke(p,"饭");//    (对象,实参)
    }

获取所有用public修饰的成员方法:

        //获取所有用public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method2 : methods) {
            System.out.println(method2);
        }

 

需要注意的是,这里的方法不仅包含Person类中显而易见的方法,还包含了Object类中的所有public修饰的方法。

(4)获取类名

        //获取类名
        String name = personClass.getName();
        System.out.println(name);

此时获取的是全类名(包名.类名)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值