反射

一、反射的简单介绍

1、什么是反射?

反射就是将类的各个组成部分封装为其他的对象,这个就是反射的机制

画图解释说明

在这里插入图片描述
字节码文件当中存放的是对应类有关成员变量、构造方法、成员方法和类的名称等信息,在硬盘上存储着

如果我们想进入第三个阶段创建对象的话,必须将硬盘中存储者的class文件加载到内存当中,我们才能调用对应类的构造方法。这时候就需要通过类加载器将class字节码文件加载到内存当中,在内存当中通过Class类来描述字节码文件,而这个类对象中包含三个比较重要的东西分别是成员变量、构造方法和成员方法。由于这三部分是不同的东西并且自己有自己的特征,所以我们把着三部分封装为其他的一些对象,成员变量封装为Field对象,构造方法封装为Constructor对象,成员方法封装为Method对象。由于一个字节码文件当中可能存在不止一个的成员变量和构造方法还有成员方法,所以这里使用了数组将成员变量封装为的对象存入了Field[ ]数组当中,构造方法封装为了的对象存入了Constructor[ ]数组当中、成员方法封装成了的对象存入到了Method[ ]数组当中

2、反射的优点

① 在程序的运行过程中,来操作这个对象
在这里插入图片描述
当我们在编译的时候打点会提示出来很多方法,而这些方法其实就是第二阶段中加载到内存当中的方法数组当中的所有方法

② 可以解耦,提高程序的可扩展性

二、获取Class对象的不同方式

1、Class.forName(“全类名”)

将字节码文件加载进内存,返回Class对象

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

举例示范

public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("Project2020.Mouth11.Day09.Person");
        System.out.println(cls);
    }

得到的结果为:
在这里插入图片描述

注意:

1、全类名的意思是类包名+类名
2、如果出现了ClassNotFoundException异常那么一定是全类名输入错误
3、Class.forName方法是个异常方法需要对它进行处理

2、类名.class

通过类名的属性class获取

*多用于参数的传递

3、对象.getClass()

通过对象打点调用getClass方法获取,该方法时Object中的方法,所以任和对象都能使用

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

注意

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

三、Class对象的功能

获取功能

1、获取成员变量们
Filed[ ] getFields( )
获取所有被public修饰的成员变量
举例说明
Person类

public class Person {
    public String a;
    public String e;
    protected String b;
    String c;
    private String d;
}

主方法类

public static void main(String[] args) {
        Class personClass = Person.class;
        Field[] fields = personClass.getFields();
        for(Field i : fields){
            System.out.println(i);
        }
    }

得到的结果为:
在这里插入图片描述

Field getField(String name)
获取指定名称的public修饰的成员变量

Field[ ] getDeclaredFields()
获取所有的成员变量,不考虑修饰符

Field getDeclaredField(String name)
获取所有成员变量中指定名字的成员变量
注意
如果我们想给获取到的被private修饰的成员变量进行设置值或者查询值的操作之前,我们需要忽略访问权限修饰符的安全检查,也称之为暴力反射

举例示范
Person类

public class Person {
    public String a;
    public String e;
    protected String b;
    String c;
    private String d;
}

主方法:

 public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class personClass = Person.class;
        Field d = personClass.getDeclaredField("d");
        d.setAccessible(true);
        Person p1 = new Person();
        d.set(p1, "这里给被private修饰的变量进行的赋值");
        System.out.println(d.get(p1));
}

得到的结果如下:
在这里插入图片描述
如果不使用暴力反射的话会出现如下结果:(会显示非法访问异常
在这里插入图片描述

2、获取构造方法(也就是构造器)们
Constructor<?>[ ] getConstructors( )
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法(被public修饰的)。
Constructor<T>[ ] getConstructors(类<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法(被public修饰的)。
Constructor<T>[ ] getDeclaredConstructors(类<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
其中当构造方法被private修饰了的话也可以通过暴力反射的方式来创建对象
Constructor<?>[ ] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
3、获取成员方法们
Method[ ] getMethods( )
Method getMethod(String name, 类<?>...parameterTypes)
Method[ ] getDeclaredMethods( )
Method getDeclaredMethod(String name, 类<?>...parameterTypes)
4、获取类名
String getName( )

Field:成员变量

1、设置值的操作

void set(Object obj, Object value)

2、获取值的操作

get(Object obj)

举例示范

Person类

public class Person {
    public String a;
    public String e;
    protected String b;
    String c;
    private String d;
}

主方法:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class personClass = Person.class;
        Field a = personClass.getField("a");
        Person p1 = new Person();
//        传递一个对象,并且赋a的值
        a.set(p1, "这里设置了a的值");
//        打印输出对象p1的a的值
        System.out.println(a.get(p1));
    }
}

运行结果为:
在这里插入图片描述

Constructor构造方法

1、T newInstance(Object... initargs)

Constructor的方法 newInstance(Object…initargs)功能//可变参数

newInstance方法是根据构造函数来生成对象

其中initargs就是你这个对象的构造函数的参数,如果构造函数是无参的,就一个也不要传,这个列表和构造函数的参数列表时一样的,只不过,当是基本数据类型传入的时候,需要一个包装类来包装它,但是jdk1.5也可以直接传入基本数据类型了,因为编译器会帮你自动装箱,拆箱

2、如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值