java 反射 内存_java_反射

java_反射

什么是反射

概念

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

java代码在内存中经历的三个阶段

1、 Source 源代码阶段

执行javac编译命令从.java文件到.class文件的过程都是在源代码阶段,.class字节码文件会将类分为多个部分,其中分为成员变量部分,成员方法部分,构造方法部分等。

2、 Class 类对象阶段

通过ClassLoader(类加载器)将字节码文件加载到内存中。

通过Class类对象来描述进入内存中的字节码文件的特征和行为。将成员变量、成员方法、构造方法等封装成单独的对象放入Class类对象中。

最后我们可以通过Class对象的一些行为创建具体的某个对象。

3、 runtime 运行时阶段

new 类();

反射的好处

在程序的运行期间操作这些对象。

降低程序的耦合性,提高程序的可扩展性。

获取Class类对象的方法

获取class类对象的方式有三种,分别对应的java代码经历的三个阶段

1、 Class.forName("全类名");

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

多用于配置文件,将类名定义在配置文件中

2、 类名.class;

通过类名的属性class获取

多用于参数传递

3、 对象.getClass();

getClass()方法是定义在Object类中的

多用于对象获取字节码

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次。

package top.uaoie.day03;

import top.uaoie.domain.Person;

public class ReflectDome01 {

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

//1. Class.forName("全类名");

Class clazz1 = Class.forName("top.uaoie.domain.Person");

//2. 类名.class;

Class clazz2 = Person.class;

//3. 对象.getClass();

Person p = new Person();

Class clazz3 = p.getClass();

System.out.println(clazz1);

System.out.println(clazz2);

System.out.println(clazz3);

//比较三个对象

System.out.println(clazz1 == clazz2);

System.out.println(clazz1 == clazz3);

}

}

65c3e1bae2f83e66868081ebc37ec814.png

反射的应用

1、 获取所有的成员变量

Field[] getFields()

Field getFied(String name)

Field[] getDeclaredFields()

Field getDeclaredFied(String name)

2、 获取所有的构造方法

Constructor>[] getConstructors()

ConstructorgetConstructors(类>... parameterTypes)

Constructor>[] getDeclaredConstructors()

ConstructorgetDeclaredConstructors(类>... parameterTypes)

3、 获取所有的成员方法

Method[] getMethods()

Menthod getMethod(String name,类>...parameterTypes)

Method[] getDeclaredMethods()

Menthod getDeclaredMethod(String name,类>...parameterTypes)

4、 获取类名

String getName()

以下为演示通过反射获取所有的成员变量

创建一个名为Person的类,里面的代码如下:

package top.uaoie.domain;

public class Person {

public String a;

protected String b;

String c;

private String d;

@Override

public String toString() {

return "Person{" +

"a='" + a + '\'' +

", b='" + b + '\'' +

", c='" + c + '\'' +

", d='" + d + '\'' +

'}';

}

}

再新建一个名为ReflectDome02的类,里面的代码如下:

package top.uaoie.day03;

import top.uaoie.domain.Person;

import java.lang.reflect.Field;

public class ReflectDome02 {

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

//获取Person的Class对象,此处是在阶段二部分获取的

//也可在第一阶段获取,如:Class.forName("top.uaoie.domain.Person");

Class p = Person.class;

//获取成员变量

Field[] fields = p.getFields();

for (Field field : fields) {

System.out.println(field);

}

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

Field a = p.getField("a");

System.out.println(a);

//创建一个对象

Person person = new Person();

//获取成员变量a的值

Object value = a.get(person);

System.out.println(value);

//设置成员变量a的值

a.set(person, "这是a的值");

System.out.println(person);

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

Field[] declaredFields = p.getDeclaredFields();

for (Field declaredField : declaredFields) {

System.out.println(declaredField);

}

Field d = p.getDeclaredField("d");

//忽略访问权限修饰符

d.setAccessible(true);//暴力反射

Object value2 = d.get(person);

System.out.println(value2);

}

}

053467168228baa9e67b1395852855f8.png

小结

获取类的class对象有多种方法,其中使用Class.forName可以通过读取配置文件获取全类名

Class.forName和getField等类是代码会报错是因为传入的是字符串,所有可能不存在这个类获或者方法,所以需要处理异常

通过反射可以直接访问到任何成员变量名,不受访问修饰符的限制

可以setAccessible设置为true来暴力反射获取或者更改成员变量的值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值