数据结构初阶:反射-->Java达成
这是下面实现的全部代码:javacode-25year: 2025年java代码
1.反射的概念
一个.java资料(如文档内只有一个类)经过编译生成.class材料,.class再被加载到JVM生成一个Class对象(实例)。(有多少个类就生成多少个Class对象,内部类也会生成单独的Class对象)
通过Java反射机制允许使用指定对象中的任何变量和方法(任何都行,包括被private 修饰的 ),甚至修改变量和方法。
2.反射相关的类
| 类名 | 用途 |
| Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
| Field类 | 代表类的成员变量/类的属性 |
| Method类 | 代表类的途径 |
| Constructor类 | 代表类的构造方法 |
2.1Class类中相关的方法
(后面有相关方法的使用示例)
- 常用获得类相关的方式
| 方法 | 用途 |
| getClassLoader() | 获得类的加载器 |
| getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的) |
| forName(String className) | 根据类名返回类的对象 |
| newInstance() | 创建类的实例 |
| getName() | 获得类的完整路径名字 |
- 常用获得类中属性相关的方法(以下方法返回值为Field相关)
方法
用途
getField(String name)
获得某个公有的属性对象
getFields()
获得所有公有的属性对象
getDeclaredField(Stringname)
获得某个属性对象
getDeclaredFields()
获得所有属性对象
- 获得类中注解相关的方法(了解)
方法
用途
getAnnotation(ClassannotationClass)
返回该类中与参数类型匹配的公有注解对象
getAnnotations()
返回该类所有的公有注解对象
getDeclaredAnnotation(ClassannotationClass)
返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()
返回该类所有的注解对象
- 获得类中构造器(构造函数)相关的方法(以下方法返回值为Constructor相关)
方法
用途
getConstructor(Class...<?> parameterTypes)
获得该类中与参数类型匹配的公有构造方法
getConstructors()
获得该类的所有公有构造方法
getDeclaredConstructor(Class...<?> parameterTypes)
获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()
获得该类所有构造方法
- 获得类中方法相关的方法(以下方法返回值为Method相关)
方法
用途
getMethod(String name, Class...<?> parameterTypes)
获得该类某个公有的方法
getMethods()
获得该类所有公有的方法
getDeclaredMethod(String name, Class...<?> parameterTypes)
获得该类某个手段
getDeclaredMethods()
获得该类所有方式
技巧:获取类对象的属性、构造方法和其他方法所使用的手段名有一个共同特征。当我们访问类对象中的公有成员时都没有加Declared,在原本获取公有成员的办法上加上Declared就可以获取某个成员,如:getMethods()——》获得该类所有公有的方法
getDeclaredMethods()——》获得该类所有方法
3.反射示例
3.1获得Class对象的技巧有三种
在反射之前,要获得需要反射的Class类对象,然后通过Class的技巧,反射要获取的成员。
第一种,运用静态方法 Class.forName("类的全路径名");
前提:已明确类的全路径名
第二种,.class 方法。
仅适用于,编译前已确定要操作的类
第三种,使用类对象的getClass();方法
示例:

下面这个实验说明JVM只会产生一个Class对象

三种生成Class对象的方法用的最多的是第一种。
3.2使用Class对象反射Student实例
所用方法上面均有。
Student类代码:
public class Student {
//私有属性name
private String name = "My age is";
//公有属性age
public int age = 18;
//不带参数的构造方法
public Student() {
System.out.println("demo1.Student()");
}
private Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("demo1.Student(String,name)");
}
private void eat() {
System.out.println("i am eat");
}
public void sleep() {
System.out.println("i am pig");
}
private void function(String str) {
System.out.println(str);
}
@Override
public String toString() {
return "demo1.Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

3.3反射私有Constructor(构造方法)

疑惑:一切都是按照逻辑写的代码为什么会报错呢?如果没报错,这里应该打印demo1.Student{name=我, age=18},上面在选构造器时已经调用了对应构造函数的实例了(name与age被重新赋值)。
解决方法:我们可能想到private本来就是为了限制访问的,但现在好了,直接反射什么都可以拿到了...,所以为了确认你是否真要反射获取私有的成员,每次都要setAccessible(true);
这里我要解释一下,catch中的全是编译错误,但为什么我要扔出运行时异常呢,是因为catch是架构自动生成的的,大家可以改;
修改后的代码:

不反射私有成员就不需要某.setAccessible() 。
3.4反射私有Field(属性)

3.5反射私有Method(方法)

4.总结
文章只讲述了反射私有属性与方法,但公有的也类似。
反射不难,只是要用到许多方式。这也说明反射的效率不会很高,我们获取私有成员也不是那么容易的,private还是有一定的安全性。

浙公网安备 33010602011771号