javase高级技术 - 反射

时间:2023-03-08 17:27:07

在说反射之前,必须得先说说java的类加载器,类加载器的定义:将.class文件加载到内在中,并为之生成对应的Class对象。

一般有三种

1 Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2 Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3 Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

接下来,我们在说反射

反射的定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。【简单来说 通过class字节码文件来获取他的构造方法,方法和属性的这种技术,叫做反射】

反射的几种用法

在使用反射之前,我们需要获取Class对象

一般有三种方式可以获得

1类名.class

2.对象.getClass()

3.使用Class.forName("类的完整包名"); 推荐使用这种。

通过反射,我们可以获取到类的构造方法,成员变量,成员方法。(包含private的)所以一般为了安全,字节码文件会加密的。

 获取构造方法

获取构造方法
  getConstructors  //返回构造方法数组
  getDeclaredConstructors //获取私有的构造方法数组
 创建对象
  newInstance()
  con.newInstance(“zhangsan", 20); //有参构造

获取成员变量

 获取所有成员
  getFields,getDeclaredFields
获取单个成员
  getField,getDeclaredField
修改成员的值
  set(Object obj,Object value)   将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

 获取成员方法

获取所有方法
 
 getMethods
  getDeclaredMethods
获取单个方法
  getMethod
  getDeclaredMethod
暴力访问
  method.setAccessible(true); //可以访问私有的

以下是代码

普通java类

package com.demo;

public class Demo {
private String name;
private int age;
public String ssss; public Demo(String name) {
this.name = name;
} public Demo() { } private Demo(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public void show() {
System.out.println(name);
} public void showString(String s) {
System.out.println("s____" + s);
} public String gets(String s) {
return s;
} @Override
public String toString() {
return ("name__" + name + "age__" + age);
}
}

  测试构造方法【目的是为了实例化对象】

@Test
public void testConstructor()
{
Class<?> dc;
try {
dc = Class.forName("com.demo.Demo");
Constructor[] cons = dc.getConstructors();
for(Constructor cc:cons)
{
System.out.println(cc);
//结果如下
//public com.demo.Demo()
//public com.demo.Demo(java.lang.String)
}
//获取单个
Constructor cc = dc.getConstructor(String.class);
Object ob = cc.newInstance("aaaa");
System.out.println(ob);
//获取私有的构造该方法
Constructor ccint = dc.getDeclaredConstructor(int.class);
ccint.setAccessible(true);//暴力访问
Object o = ccint.newInstance(111);
System.out.println(o); //结果 age__111
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }

  测试成员变量以及成员方法

	@Test
public void testFieldAndMethod() {
Class<?> dc;
try {
dc = Class.forName("com.demo.Demo");
Field[] fields = dc.getDeclaredFields(); //获取所有的成员变量 包含私有的 for (Field f : fields) {
System.out.println(f.toString());
}
// 结果如下
// private java.lang.String com.demo.Demo.name
// private int com.demo.Demo.age
// public java.lang.String com.demo.Demo.ssss
Field nameField = dc.getDeclaredField("name");
// 暴力访问
nameField.setAccessible(true);
Constructor cc = dc.getConstructor(String.class);
Object ob = cc.newInstance("string");
//赋值语句
nameField.set(ob, "name test ");
System.out.println(ob); //结果 name__name test
//3成员方法
Method showStringMethod = dc.getDeclaredMethod("showString", String.class);
showStringMethod.invoke(ob, "ssss"); //通过invok执行
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }