反射

# 反射

## 概述

java反射机制是在程序**运行状态**
中,对于任意一个类,都能够知道这个类的所有的属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称之为java的反射机制。

要想解剖一个类,必须先要获取这个类的字节码文件对象。解剖这个类,使用的就是Class类中的方法。字节码文件对象就对应到Class类型的对象

要掌握的单词:

– Class 类
– Constructor 构造方法
– Method 方法
– Field 属性
– Instance 实例
– invoke 执行

## 获取Class对象

“
通过类字面量:

“`
Class clazz = String.class;
“`

通过对象实例:

“`
String str = “Hello”;
Class clazz = str.getClass();
“`

通过 Class.forName() 方法:

“`
Class clazz = Class.forName(“java.lang.String”);
“`

## 创建对象

可以使用反射动态创建对象:

“`
Class clazz = Class.forName(“java.lang.String”);
Object obj = clazz.getDeclaredConstructor().newInstance();
“`

“`java
import java.util.ArrayList;
import java.util.List;

public class AddUserTest {
public static void main(String[] args) throws ClassNotFoundException {
//获取Class对象
//方式一
//接口名/类名.class
Class stringClass = String.class;
System.out.println(stringClass);

Class lsitclass = List.class;
System.out.println(lsitclass);

Class aclass = int[].class;
System.out.println(aclass);

Class integerClass = Integer.class;
System.out.println(integerClass);

Class doubleClass = Double.class;
System.out.println(doubleClass);

//对象名.getClass();
//方式二

List list = new ArrayList();
System.out.println(list.getClass());

//方式三
//字符串必须是全路径名

Class aClass1 = Class.forName(“java.util.Date”);
System.out.println(aClass1);

Class aClass2 = Class.forName(“cn.javasm.Testdemo”);
System.out.println(aClass2);
}
}
“`

## 访问字段

可以通过反射访问和修改类的字段:

“`
Class clazz = Person.class;
Field field = clazz.getDeclaredField(“name”);

// 如果字段是私有的,需要设置为可访问
field.setAccessible(true);

// 获取字段值
Object value = field.get(personInstance);
// 设置字段值
field.set(personInstance, “New Name”);
“`

“`java
import java.lang.reflect.Field;

public class TestDemo3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 获取字符串的hash属性
// 获取字节码文件对象
Class stringClass = String.class;
// 获取serialVersionUID属性
// stringClass.getDeclaredField(“serialVersionUID”);
// stringClass.getDeclaredFields();

Field field = stringClass.getDeclaredField(“hash”);
System.out.println(field);
//暴力破解
String str = “abc”;
field.setAccessible(true);
field.set(“str”, 10);
Object obj = field.get(str);
System.out.println(obj);
//获取所有的属性
Field[] declaredFields = stringClass.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f);
}
//获取属性的修饰符
int modifiers = field.getModifiers();
System.out.println(modifiers);

Class personClass = Person.class;
Field name = personClass.getDeclaredField("name");
System.out.println(name);
System.out.println(name.getModifiers());
}
}

“`

### 修饰符对应返回值

![image-20241030111223439.png](http://43.155.216.63:21080/wp-content/uploads/2025/12/image-20241030111223439.png

## 调用方法

可以通过反射调用类的方法:

“`
Class clazz = Person.class;
Method method = clazz.getMethod(“sayHello”);
method.invoke(personInstance);

Method methodWithArgs = clazz.getMethod(“greet”, String.class);
methodWithArgs.invoke(personInstance, “World”);
“`

获取公共方法 & 获取非公开的方法

“`java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestDemo4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// method1();
// method2();
}

private static void method2() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
//获取字节码文件对象
Class staringClass = String.class;
//获取公共方法
Method method = staringClass.getMethod(“substring”, int.class, int.class);
String str = “abcd”;
// 执行方法
// 参数一 要执行的对象
// 参数二 方法的实参
// 返回值就是方法的返回值
Object invoke = method.invoke(str, 1, 3);
System.out.println(invoke);
}

private static void method1() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//获取字节码文件对象
Class personClass = Person.class;
//获取非公开的方法
Method method = personClass.getDeclaredMethod(“eat”);
Person person = new Person(“cyz”, 22);
//暴力破解
method.setAccessible(true);
//执行方法
Object invoke = method.invoke(person);
System.out.println(invoke);
}
}

“`

获取枚举类

“`java
public class TestDemo5 {
public static void main(String[] args) {
// 获取字节码文件对象
Class levelClass = Level.class;
// 获取枚举Level中的所有的枚举常量
Level[] enumConstants = levelClass.getEnumConstants();
for (Level enumConstant : enumConstants) {
System.out.println(enumConstant);
}

}

enum Level {
A, B, C, D, E
}
}
“`

如果不是枚举 返回null

“`java
public static void method2() {
Class stringClass = String.class;
String[] enumConstants1 = stringClass.getEnumConstants();
System.out.println(enumConstants1);

}
“`

## 获取接口和父类

可以使用反射获取类实现的接口和父类:

“`
Class clazz = Person.class;

// 获取所有接口
Class[] interfaces = clazz.getInterfaces();
for (Class i : interfaces) {
System.out.println(“Interface: ” + i.getName());
}

// 获取父类
Class superClass = clazz.getSuperclass();
System.out.println(“Superclass: ” + superClass.getName());
“`

获取所有接口

“`java
public class TestDemo6 {
public static void main(String[] args) {
Class stringClass = String.class;
Class[] interfaces = stringClass.getInterfaces();
for (Class i : interfaces) {
System.out.println(i);
}
}
}
“`

// 获取父类 全路径类名 类名 包名

“`java
public class TestDemo6 {
public static void main(String[] args) {
Class stringClass = String.class;

//获取父类
Class superclass = stringClass.getSuperclass();
System.out.println(superclass);

//获取全路径类名
String name = superclass.getName();
System.out.println(name);

//获取简单类名
String simpleName = superclass.getSimpleName();
System.out.println(simpleName);

//获取包名
System.out.println(stringClass.getPackageName());
}
}

“`

## 获取构造方法

可以使用反射获取和调用构造函数:

“`
Class clazz = Person.class;
Constructor constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance(“John”, 30);
“`

“`java
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestDemo2 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取字符串字节码文件对象
Class stringClass = String.class;
// 获取构造方法
//public String(byte ascii[], int hibyte, int offset, int count)
Constructor constructor = stringClass.getConstructor(byte[].class, int.class, int.class);
// 创建对象
String string = constructor.newInstance(new byte[]{97, 98, 99}, 0, 3);
System.out.println(string);

//获取所有公共的构造方法
Constructor[] constructors = stringClass.getConstructors();
for (Constructor constructor1 : constructors) {
System.out.println(constructor1);
}

//获取指定的构造方法
Constructor declaredConstructor = stringClass.getDeclaredConstructor(byte[].class, int.class, int.class);

System.out.println(declaredConstructor);

//暴力破解
declaredConstructor.setAccessible(true);

String s1 = declaredConstructor.newInstance(new byte[]{97, 98, 99});
System.out.println(s1);

//获取所有构造方法
Constructor[] declaredConstructors = stringClass.getDeclaredConstructors();
for (Constructor declaredConstructor1 : declaredConstructors) {
System.out.println(declaredConstructors);
}
}
}

“`

## 反射劣势

1 反射打破了封装原则

2 可以跳过泛型检查

“`java
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List list = new ArrayList<>();
// 获取字节码文件对象
Class aClass = list.getClass();
// 获取add方法
Method method = aClass.getMethod(“add”, Object.class);
// 执行方法
method.invoke(list, 12);
System.out.println(list);
}

“`

## Method和Field相关方法

## 判断方法

“`java
@FirstAnno(“abc”)
public class TestDemo10 {

int j = 20;

public static void main(String[] args) {

int i = 10;

}
}

// 自定义注解
@interface FirstAnno {
// 在注解中可以定义属性,默认被public static final修饰
public static final int i = 10;

// 在注解中定义变量 使用()
// 注解中的属性使用public修饰
// String str();
//
// double d();
// 设置默认值
char c() default ‘国’;

// 注解中的属性类型只能是基本数据类型/String/Class/注解/枚举以及它们的一维数组形式
// Object obj();
// 如果数组中只有一个元素, {} 可以省略
// int[] arr();
// 如果传递值时只有一个值,并且名称是value,那么可以省略value =
String value();
}

“`

## 注解

### 自定义注解

“`java
@FirstAnno(“abc”)
public class TestDemo10 {

int j = 20;

public static void main(String[] args) {

int i = 10;

}
}

// 自定义注解
@interface FirstAnno {
// 在注解中可以定义属性,默认被public static final修饰
public static final int i = 10;

// 在注解中定义变量 使用()
// 注解中的属性使用public修饰
// String str();
//
// double d();
// 设置默认值
char c() default ‘国’;

// 注解中的属性类型只能是基本数据类型/String/Class/注解/枚举以及它们的一维数组形式
// Object obj();
// 如果数组中只有一个元素, {} 可以省略
// int[] arr();
// 如果传递值时只有一个值,并且名称是value,那么可以省略value =
String value();
}
“`

### 元注解

对注解进行注解的那些注解

“`java
@Target({ElementType.METHOD, ElementType.TYPE}) // 限定注解的使用范围
@Retention(RetentionPolicy.RUNTIME) //限定注解的存活范围
@Inherited // 表示这个注解也要作用在子类上
@Documented // 表示这个注解会生成到java文档中
“`

### 10.3 反射注解

“`java
public class TestDemo11 {
public static void main(String[] args) throws NoSuchMethodException {
// 获取字节码文件对象
Class teacherClass = Teacher.class;
Method method = teacherClass.getMethod(“teach”);
// 判断类或者方法或者属性上面是否有指定的注解isAnnotationPresent
if (teacherClass.isAnnotationPresent(Anno.class)) {
// 获取所有注解
// teacherClass.getAnnotations();
Anno annotation = teacherClass.getAnnotation(Anno.class);
// 获取注解的值
String value = annotation.value();
if (“初级”.equals(value)) {
System.out.println(“认真负责”);
} else if (“中级”.equals(value)) {
System.out.println(“三尺讲台,两袖清风”);
} else if (“特级”.equals(value)) {
System.out.println(“桃李满天下”);
} else {
System.out.println(“辅导员…”);
}
} else {
System.out.println(“野鸡老师……”);
}
}
}

@Anno(“特级”)
class Teacher {

public void teach() {
System.out.println(“老师要教书育人”);
}
}

@Retention(RetentionPolicy.RUNTIME)// 保留到运行阶段
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Anno {
String value();
}
“`

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇