java反射重要么_JAVA反射----这些知识你需要知道

前言:

在学习JAVA的反射之前我觉得很有必要花几分钟时间了解一下JVM的内存结构。如果一开始就说什么是反射,以及反射的API。这样做是很难真正的理解反射的。

d908bbfe0c3f5f39d240774433b1a889.png

JVM是JAVA跨平台的核心,其结构为上图所示。我们注意到其运行时数据区也就是我们常说的内存结构包括堆区,方法区,栈区等。那么我们JAVA程序在运行的时候,运行时数据区每个区域存储的哪些数据呢。

程序计数器:简单将程序计数器就是用来指示需要执行哪条指令。由此看出它是线程私有的,因为我们知道多线程的本质是线程抢占CPU时间片的过程,所以我们线程中指令不断的终止和运行,所以要回到运行状态必须要程序计数器记录下应该执行的指令编号。(因为每天指令的大小是固定的所以不会存在内存泄漏的情况)

JAVA栈:JAVA栈也称为JAVA执行方法的内存模型,存储了方法中声明的局部变量包括声明的局部变量形参,运行时常量池引用以及返回地址。JAVA的运行其实就是一个方法栈帧的压栈与弹栈的过程。

堆区:Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。只不过和C语言中的不同,在Java中,程序员基本不用去关心空间释放的问题,Java的垃圾回收机制会自动进行处理。因此这部分空间也是Java垃圾收集器管理的主要区域。另外,堆是被所有线程共享的,在JVM中只有一个堆。

方法区:方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。在Class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。在方法区中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。当然并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。

类加载的过程其实就是JVM将外部的静态class字节码加载到JVM方法区形成动态数据并在堆中形成一个java.lang.Class对象。这个对象相当于一面镜子与方法区中真正对象对应,这个Class对象就是反射的核心。

了解Class

既然Class对象是反射的核心,那么什么是Class呢?我们来看一下JDK7中是怎么定义的:

* Instances of the class{@code Class} represent classes and* interfaces in a running Java application. An enumis a kind of* class and an annotation is a kind of interface. Every array also* belongs to a classthat is reflected as a {@code Class} object*that is shared by all arrays with the same element type and number* of dimensions. The primitive Java types ({@code boolean},* {@code byte}, {@code char}, {@code short},* {@code int}, {@code long}, {@code float}, and* {@code double}), and the keyword {@code void} are also*represented as {@code Class} objects.*

*

{@code Class} has no publicconstructor. Instead {@code Class}*objects are constructed automatically by the Java Virtual Machine as classes* are loaded and by calls to the {@code defineClass} method in the class

* loader.

大概意思为:Class的实例代表正在运行JAVA程序中的对象和接口。枚举类型是一种对象而注解是一种接口。每个数组是被映射为Class的一个类,而具有相同数据类型和维数的数组都共享该Class类。基本数据类型依然是Class对象。Class没有公共的构造方法。所有的Class对象都是在JVM被加载的时候自动调用defineClass创建。

反射作用

可以通过反射得到类成员变量,成员方法以及构造方法并可以操作他们,即使是私有的也可以访问并操作。

提高代码灵活性

反射示例

首先创建一个测试Student类:

public classStudent {private intage;privateString name;private double score; //三个私有属性

public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public doublegetScore() {returnscore;

}public void setScore(doublescore) {this.score =score;

}public Student(){//公共不带参构造

}private Student(int age,String name,double score){//私有带参构造

this.age =age;this.name =name;this.score =score;

}

}

三种方式获取Class对象:

Class clazz1 = Class.forName("reflection.Student");

Class clazz2= Student.class;

Student student= newStudent();

Class clazz3=student.getClass();

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

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

输出结果为:ture/ture 根据传递性可知这三个对象是同一个

2.通过反射得到实例对象

Class clazz1 = Class.forName("reflection.Student");

Object obj= clazz1.newInstance();//调用了无参构造函数

3.通过反射得到类私有变量并赋值

Class clazz1 = Class.forName("reflection.Student");

Object o=clazz1.newInstance();

Field files1= clazz1.getDeclaredField("age");

files1.setAccessible(true); //打破私有访问属性

files1.set(o, 12);

System.out.println(files1.get(o));

4.通过反射执行私有构造函数

Constructor a = clazz1.getDeclaredConstructor(int.class,String.class,double.class);

a.setAccessible(true);

Student stu= (Student)a.newInstance(12,"李强",12);

System.out.println("学生信息获取到:"+stu.getName());

5.通过反射执行成员方法

Constructor a = clazz1.getDeclaredConstructor(int.class,String.class,double.class);

a.setAccessible(true);

Student stu= (Student)a.newInstance(12,"李强",12);

System.out.println("学生信息获取到:"+stu.getName());

Method method= clazz1.getMethod("setName", String.class);

method.invoke(stu,"芳芳");

System.out.println("学生信息获取到:"+stu.getName());

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值