Notes Site.
post @ 2023-10-13

Java反射&动态代理

反射机制

Java 反射(Reflection)是一种机制,它允许 Java 程序在运行时获取和操作它本身的数据结构,比如类、方法、属性等。通过反射,我们可以动态地创建对象、调用方法、访问属性等,而无需在编译时知道这些信息。

Java 反射主要包括以下几个核心类:

  1. Class 类:表示一个类或接口,包含了获取类信息的方法,如获取类名、父类、接口、属性、方法等。
  2. Constructor 类:表示一个构造函数,包含了获取构造函数信息的方法,如获取构造函数名、参数列表等。
  3. Field 类:表示一个属性,包含了获取属性信息的方法,如获取属性名、类型、访问权限等。
  4. Method 类:表示一个方法,包含了获取方法信息的方法,如获取方法名、参数列表、返回类型等。

以下是一些 Java 反射的常见用法:

  1. 获取类信息:通过 Class.forName() 方法获取某个类的 Class 对象,然后使用 Class 对象的各种方法获取类的信息,如 getName() 获取类名,getDeclaredMethods() 获取所有方法等。
  2. 创建对象:通过 Class 对象的 getConstructor()getDeclaredConstructor() 方法获取指定构造函数的引用,然后使用 newInstance()newInstance() 方法创建对象。
  3. 访问属性:通过 Class 对象的 getDeclaredField() 方法获取指定属性的引用,然后使用 set()get() 方法设置或获取属性的值。
  4. 调用方法:通过 Class 对象的 getDeclaredMethod() 方法获取指定方法的引用,然后使用 invoke() 方法调用方法并传递参数。
  5. 动态代理:通过 Java 反射实现动态代理,可以在运行时创建一个实现了指定接口的代理类,并实现指定的方法逻辑。

Class类就是通过FieldMethod来描述类中的字段和方法

代码

Person 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package net.Seck2y.a02;

public class Person {
private String name = "zhangsan";
private int age = 23;

public Person(){}

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public void action(String string){
System.out.println(string);
}

// 重写 toString,规定打印格式,不规定会输出 类 和 地址
@Override
public String toString(){
return "Person{" +
"name: " + this.name +
", age: "+ this.age +
"}";
}
}

Reflection 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package net.Seck2y.a02;

import java.lang.reflect.*;

public class Reflection {
public static void main(String[] args) throws Exception {
// Class<?>
// 获取 Person 类的 Class 对象(两种形式)
// Class<?> personClass = Person.class;
Class<?> personClass = Class.forName("net.Seck2y.a02.Person"); // 完整路径


// Constructor<?>
// 获取 Person 类的构造方法
Constructor<?> constructor = personClass.getConstructor(String.class, int.class);

// 创建 Person 对象
Object person = constructor.newInstance("lisi", 24);
System.out.println(person);
// 输出 Person{name: lisi, age: 24}


// Field
// 获取成员属性的信息(无值)
Field[] personField = personClass.getDeclaredFields();
for (Field f:personField){
System.out.println(f);
}
/* 输出
private java.lang.String net.Seck2y.a02.Person.name
private int net.Seck2y.a02.Person.age
*/

// 获取成员属性的值
Field nameField = personClass.getDeclaredField("name");
Field ageField = personClass.getDeclaredField("age");
nameField.setAccessible(true); // 提权
ageField.setAccessible(true); // 提权
String name = (String) nameField.get(person); // 获取 nameField 属性的值
int age = (int) ageField.get(person); // 获取 ageField 属性的值
System.out.println(
nameField.getName() + ": " + name + ", " +
ageField.getName() + ": " + age);
// getName 获取属性的名称
// System.out.println(person); 可替换
// 输出 name: lisi, age: 24

// 修改成员属性的值
Field setName = personClass.getDeclaredField("name");
Field setAge = personClass.getDeclaredField("age");
setName.setAccessible(true);
setAge.setAccessible(true);
setName.set(person, "wangwu");
setAge.set(person, 25);
System.out.println(
setName.getName() + ": " +setName.get(person) + ", " +
setAge.getName() + ": " + setAge.get(person));
// System.out.println(person); 可替换
// 输出 name: wangwu, age: 25


// Method
// 获取方法
Method[] personMethod = personClass.getDeclaredMethods();
for (Method m: personMethod) {
System.out.println(m);
}
/* 输出
public java.lang.String net.Seck2y.a02.Person.toString()
public void net.Seck2y.a02.Person.action(java.lang.String)
*/

// 获取 Person 对象的方法信息并调用它们
Method actionMethod = personClass.getMethod("action",String.class);
actionMethod.invoke(person,"Reflection");
// 输出 Reflection
}
}

Class

Read More
post @ 2023-10-10

Java基础

Hello World

编译运行

1
2
3
java源文件 -> class字节码文件 -> java运行class文件
javac java文件 # 输出class字节码文件
java class文件

Hello World

1
2
3
4
5
public class HelloWord {  // 与文件名一致
public static void main(String[] args) { // 主函数
System.out.println("Hello World");
}
}

主函数

1
2
3
public static void main(String[] args){

}

输入输出

1
2
3
4
5
6
7
8
9
10
11
12
13
输入
import java.util.Scanner

Scanner sc = new Scanner(System.in);

int q = sc.nextInt();
String c = sc.next();

输出
System.out.println(值); // 换行
sout // 匹配

System.out.print(值); // 不换行
Read More
⬆︎TOP