读书日记三

前言

每天一小步,进步一大步。java 反射

0x01 java.lang.Class类
getClass()方法
Object类有一个getClass()方法,它返回对的引用类对象的类对象。
以下代码显示如何获取对Test类的Class对象的引用:
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.demo;

class Perso{

}

public class Test11 {
public static void main(String[] args) {
Perso perso=new Perso();
Class<?> personClass=perso.getClass();
System.out.println(personClass);
}
}
结果如下:
1
class com.example.demo.Perso
forName()方法
Class类forName()static方法返回对Class对象的引用。
它的重载方法是
1
2
Class<?>   forName(String  className)
Class<?> forName(String name, boolean initialize, ClassLoader loader)
forName()方法的第一个版本接受完全该类的限定名作为参数,并加载该类,并返回其对象引用。
如果类已经加载,它将返回对Class对象的引用。
第二版本方法可以控制是否初始化或不初始化该类在加载时。 我们也可以传入类加载器。
下面的代码显示了如何加载一个类并获取对它的Class对象的引用。
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
package com.example.demo;

class MyClass {
static {
System.out.println("Loading class MyClass...");
}
}

public class Test11 {
public static void main(String[] args) {
try {
String className = "MyClass";
boolean initialize = false;

ClassLoader cLoader = Test11.class.getClassLoader();
Class<?> c = Class.forName(className, initialize, cLoader);

className = "MyClass";
System.out.println("about to load");
c = Class.forName(className);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Java类反射
我们可以使用Java反射来获取关于类的信息,例如作为其包名称,其访问修饰符等。
要获得简单的类名,请使用 Class 中的 getSimpleName()方法。
String simpleName = c.getSimpleName();
类的修饰符是关键字之前的关键字类在类声明中,如 abstract , public 。
Class 中的 getModifiers()方法返回类的所有修饰符。
getModifiers()方法返回一个整数。我们必须调用 java.lang.reflect.Modifier.toString(int modifiers)以获得修饰符的文本形式。
要获取超类的名称,请使用 Class 中的 getSuperclass()方法。
如果对Object类调用getSuperclass()方法,它将返回null,因为它没有超类。
要获取类实现的所有接口的名称,请使用 getInterfaces()。
1
Class[] interfaces = c.getInterfaces();
例子:
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.example.demo;

import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;

class MyClass<T> implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private int id = -1;
private String name = "Unknown";

public MyClass(int id, String name) {
this.id = id;
this.name = name;
}

public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
}

public String toString() {
return "MyClass: id=" + this.id + ", name=" + this.name;
}
}

public class Test11 {
public static void main(String[] args) {
// Print the class declaration for the Class class
String classDesciption = getClassDescription(MyClass.class);
System.out.println(classDesciption);
}

public static String getClassDescription(Class<?> c) {
StringBuilder classDesc = new StringBuilder();
int modifierBits = 0;
String keyword = "";
if (c.isInterface()) {
modifierBits = c.getModifiers() & Modifier.interfaceModifiers();
if (c.isAnnotation()) {
keyword = "@interface";
} else {
keyword = "interface";
}
} else if (c.isEnum()) {
modifierBits = c.getModifiers() & Modifier.classModifiers();
keyword = "enum";
}
modifierBits = c.getModifiers() & Modifier.classModifiers();
keyword = "class";

String modifiers = Modifier.toString(modifierBits);
classDesc.append(modifiers);
classDesc.append(" " + keyword);
String simpleName = c.getSimpleName();
classDesc.append(" " + simpleName);

String genericParms = getGenericTypeParams(c);
classDesc.append(genericParms);

Class<?> superClass = c.getSuperclass();
if (superClass != null) {
String superClassSimpleName = superClass.getSimpleName();
classDesc.append(" extends " + superClassSimpleName);
}
String interfaces = Test11.getClassInterfaces(c);
if (interfaces != null) {
classDesc.append(" implements " + interfaces);
}
return classDesc.toString();
}

public static String getClassInterfaces(Class<?> c) {
Class<?>[] interfaces = c.getInterfaces();
String interfacesList = null;
if (interfaces.length > 0) {
String[] interfaceNames = new String[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
interfaceNames[i] = interfaces[i].getSimpleName();
}
interfacesList = String.join(", ", interfaceNames);
}
return interfacesList;
}

public static String getGenericTypeParams(Class<?> c) {
StringBuilder sb = new StringBuilder();
TypeVariable<?>[] typeParms = c.getTypeParameters();

if (typeParms.length > 0) {
String[] paramNames = new String[typeParms.length];
for (int i = 0; i < typeParms.length; i++) {
paramNames[i] = typeParms[i].getTypeName();
}
sb.append("<");
String parmsList = String.join(",", paramNames);
sb.append(parmsList);
sb.append(">");
}
return sb.toString();
}
}
结果如下:
1
class MyClass<T>  extends Object  implements Cloneable, Serializable
java字段反射
我们可以使用java.lang.reflect.Field类来获取关于类中的字段的信息。
以下四种方法在Class类可以返回关于字段的 Field 对象。
1
2
3
4
Field[] getFields()
Field[] getDeclaredFields()
Field getField(String name)
Field getDeclaredField(String name)
getFields()方法返回所有可访问的公共字段在类中声明或继承自超类。
getDeclaredFields()方法返回所有字段只出现在类的声明中(不是从继承的字段)。
getField(String name)getDeclaredField(String name)通过字段名获取Field对象。
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
package com.example.demo;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

class MySuperClass {
public int super_id = -1;
public String super_name = "Unknown";
}

class MyClass extends MySuperClass {
public int id = -1;
public String name = "Unkown";
}

public class Test12 {
public static void main(String[] args) {
Class<MyClass> c = MyClass.class;

// Print declared fields
ArrayList<String> fieldsDesciption = getDeclaredFieldsList(c);

System.out.println("Declared Fields for " + c.getName());
for (String desc : fieldsDesciption) {
System.out.println(desc);
}
fieldsDesciption = getFieldsList(c);

System.out.println("\nAccessible Fields for " + c.getName());
for (String desc : fieldsDesciption) {
System.out.println(desc);
}
}

public static ArrayList<String> getFieldsList(Class<?> c) {
Field[] fields = c.getFields();
ArrayList<String> fieldsList = getFieldsDesciption(fields);
return fieldsList;
}

public static ArrayList<String> getDeclaredFieldsList(Class<?> c) {
Field[] fields = c.getDeclaredFields();
ArrayList<String> fieldsList = getFieldsDesciption(fields);
return fieldsList;
}

public static ArrayList<String> getFieldsDesciption(Field[] fields) {
ArrayList<String> fieldList = new ArrayList<>();

for (Field f : fields) {
int mod = f.getModifiers() & Modifier.fieldModifiers();
String modifiers = Modifier.toString(mod);

Class<?> type = f.getType();
String typeName = type.getSimpleName();

String fieldName = f.getName();

fieldList.add(modifiers + " " + typeName + " " + fieldName);
}

return fieldList;
}
}
结果如下:
1
2
3
4
5
6
7
8
9
Declared Fields for com.example.demo.MyClass
public int id
public String name

Accessible Fields for com.example.demo.MyClass
public int id
public String name
public int super_id
public String super_name
java方法反射
java.lang.reflect.Method类的实例表示一个方法。 java.lang.reflect.Constructor类的实例表示一个构造函数。
方法构造方法继承自一个通用的抽象超类可执行
可执行文件中的参数由Parameter类的对象表示
Executable类中的getParameters()方法获取所有参数作为Parameter的数组。
默认情况下,参数名称不存储在类文件中。参数类的名称将类似于arg0,arg1等。我们可以通过编译源来保存类文件中的实际参数名代码使用-parameters选项与javac编译器。
可执行文件中的getExceptionTypes()方法类返回一个由Executable抛出的异常数组。
Executable类的getModifiers()方法将修饰符作为int返回。
来自Executable类的getTypeParameters()方法返回一个TypeVariable数组,该数组表示通用方法或构造函数的类型参数。
例子:
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
package com.example.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;

class MyClass<T> {

public MyClass(int i, int j, String s) {

}

public MyClass(T t) {

}

public int getInt(String a) {
return 0;
}
}

public class Test12 {
public static void main(String[] argv) {
Class<MyClass> cls = MyClass.class;

for (Method m : cls.getMethods()) {
System.out.println(m.getName());
System.out.println(getModifiers(m));
System.out.println(getParameters(m));
System.out.println(getExceptionList(m));
}
}

public static ArrayList<String> getParameters(Executable exec) {
Parameter[] parms = exec.getParameters();
ArrayList<String> parmList = new ArrayList<>();
for (int i = 0; i < parms.length; i++) {

int mod = parms[i].getModifiers() & Modifier.parameterModifiers();
String modifiers = Modifier.toString(mod);
String parmType = parms[i].getType().getSimpleName();
String parmName = parms[i].getName();
String temp = modifiers + " " + parmType + " " + parmName;
if (temp.trim().length() == 0) {
continue;
}
parmList.add(temp.trim());
}
return parmList;
}

public static ArrayList<String> getExceptionList(Executable exec) {
ArrayList<String> exceptionList = new ArrayList<>();
for (Class<?> c : exec.getExceptionTypes()) {
exceptionList.add(c.getSimpleName());
}
return exceptionList;
}

public static String getModifiers(Executable exec) {
int mod = exec.getModifiers();
if (exec instanceof Method) {
mod = mod & Modifier.methodModifiers();
} else if (exec instanceof Constructor) {
mod = mod & Modifier.constructorModifiers();
}
return Modifier.toString(mod);
}
}
结果如下:
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
getInt
public
[String a]
[]
wait
public final native
[long arg0]
[InterruptedException]
wait
public final
[long arg0, int arg1]
[InterruptedException]
wait
public final
[]
[InterruptedException]
equals
public
[Object arg0]
[]
toString
public
[]
[]
hashCode
public native
[]
[]
getClass
public final native
[]
[]
notify
public final native
[]
[]
notifyAll
public final native
[]
[]
反射方法
以下四个方法在Class类中返回有关联的方法的信息
1
2
3
4
Method[]  getMethods()
Method[] getDeclaredMethods()
Method getMethod(String name, Class... parameterTypes)
Method getDeclaredMethod(String name, Class... parameterTypes)
getMethods()方法返回该类的所有可访问的公共方法无论从类中还是继承自超类。
getDeclaredMethods()方法返回所有只在中声明的方法该类(不包括从超类继承的方法)。
getMethod(String name,Class … parameterTypes)和getDeclaredMethod(String name,Class … parameterTypes)通过方法名和参数类型获取Method对象。
Method类中的getReturnType()方法返回包含有关返回类型信息的Class对象。
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.example.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;

class MyClass<T> {

public MyClass(int i, int j, String s) {

}

public MyClass(T t) {

}

public int getInt(String a) {
return 0;
}
}

public class Test12 {
public static void main(String[] args) {
Class<MyClass> c = MyClass.class;

ArrayList<String> methodsDesciption = getDeclaredMethodsList(c);
System.out.println("Declared Methods for " + c.getName());
for (String desc : methodsDesciption) {
System.out.println(desc);
}
methodsDesciption = getMethodsList(c);
System.out.println("\nMethods for " + c.getName());
for (String desc : methodsDesciption) {
System.out.println(desc);
}

}

public static ArrayList<String> getMethodsList(Class<?> c) {
Method[] methods = c.getMethods();
ArrayList<String> methodsList = getMethodsDesciption(methods);
return methodsList;
}

public static ArrayList<String> getDeclaredMethodsList(Class<?> c) {
Method[] methods = c.getDeclaredMethods();
ArrayList<String> methodsList = getMethodsDesciption(methods);
return methodsList;
}

public static ArrayList<String> getMethodsDesciption(Method[] methods) {
ArrayList<String> methodList = new ArrayList<>();

for (Method m : methods) {
String modifiers = getModifiers(m);

Class<?> returnType = m.getReturnType();
String returnTypeName = returnType.getSimpleName();

String methodName = m.getName();

String params = getParameters(m).toString();

String throwsClause = getExceptionList(m).toString();

methodList.add(modifiers + " " + returnTypeName + " " + methodName
+ "(" + params + ") " + throwsClause);
}

return methodList;
}

public static ArrayList<String> getParameters(Executable exec) {
Parameter[] parms = exec.getParameters();
ArrayList<String> parmList = new ArrayList<>();
for (int i = 0; i < parms.length; i++) {

int mod = parms[i].getModifiers() & Modifier.parameterModifiers();
String modifiers = Modifier.toString(mod);
String parmType = parms[i].getType().getSimpleName();
String parmName = parms[i].getName();
String temp = modifiers + " " + parmType + " " + parmName;
if (temp.trim().length() == 0) {
continue;
}
parmList.add(temp.trim());
}
return parmList;
}

public static ArrayList<String> getExceptionList(Executable exec) {
ArrayList<String> exceptionList = new ArrayList<>();
for (Class<?> c : exec.getExceptionTypes()) {
exceptionList.add(c.getSimpleName());
}
return exceptionList;
}

public static String getModifiers(Executable exec) {
int mod = exec.getModifiers();
if (exec instanceof Method) {
mod = mod & Modifier.methodModifiers();
} else if (exec instanceof Constructor) {
mod = mod & Modifier.constructorModifiers();
}
return Modifier.toString(mod);
}
}
结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Declared Methods  for com.example.demo.MyClass
public int getInt([String a]) []

Methods for com.example.demo.MyClass
public int getInt([String a]) []
public final native void wait([long arg0]) [InterruptedException]
public final void wait([long arg0, int arg1]) [InterruptedException]
public final void wait([]) [InterruptedException]
public boolean equals([Object arg0]) []
public String toString([]) []
public native int hashCode([]) []
public final native Class getClass([]) []
public final native void notify([]) []
public final native void notifyAll([]) []
java构造函数反射
以下四种方法来自Class类获取有关构造函数的信息:
1
2
3
4
Constructor[] getConstructors()
Constructor[] getDeclaredConstructors()
Constructor<T> getConstructor(Class... parameterTypes)
Constructor<T> getDeclaredConstructor(Class... parameterTypes)
getConstructors()方法返回当前和超类的所有公共构造函数。
getDeclaredConstructors()方法返回当前类的所有声明的构造函数。
getConstructor(Class … parameterTypes)和getDeclaredConstructor(Class … parameterTypes)通过参数类型获取构造函数对象。
以下代码显示了如何对构造函数执行反射。
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
79
80
81
82
83
84
85
package com.example.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;

class MyClass<T> {

public MyClass(int i, int j, String s) {

}

public MyClass(T t) {

}

public int getInt(String a) {
return 0;
}
}

public class Test12 {
public static void main(String[] args) {
Class<MyClass> c = MyClass.class;

System.out.println("Constructors for " + c.getName());
Constructor<?>[] constructors = c.getConstructors();
ArrayList<String> constructDescList = getConstructorsDesciption(constructors);
for (String desc : constructDescList) {
System.out.println(desc);
}
}

public static ArrayList<String> getConstructorsDesciption(
Constructor<?>[] constructors) {
ArrayList<String> constructorList = new ArrayList<>();
for (Constructor<?> constructor : constructors) {
String modifiers = getModifiers(constructor);

String constructorName = constructor.getName();

constructorList.add(modifiers + " " + constructorName + "("
+ getParameters(constructor) + ") " + getExceptionList(constructor));
}
return constructorList;
}
public static ArrayList<String> getParameters(Executable exec) {
Parameter[] parms = exec.getParameters();
ArrayList<String> parmList = new ArrayList<>();
for (int i = 0; i < parms.length; i++) {

int mod = parms[i].getModifiers() & Modifier.parameterModifiers();
String modifiers = Modifier.toString(mod);
String parmType = parms[i].getType().getSimpleName();
String parmName = parms[i].getName();
String temp = modifiers + " " + parmType + " " + parmName;
if (temp.trim().length() == 0) {
continue;
}
parmList.add(temp.trim());
}
return parmList;
}

public static ArrayList<String> getExceptionList(Executable exec) {
ArrayList<String> exceptionList = new ArrayList<>();
for (Class<?> c : exec.getExceptionTypes()) {
exceptionList.add(c.getSimpleName());
}
return exceptionList;
}

public static String getModifiers(Executable exec) {
int mod = exec.getModifiers();
if (exec instanceof Method) {
mod = mod & Modifier.methodModifiers();
} else if (exec instanceof Constructor) {
mod = mod & Modifier.constructorModifiers();
}
return Modifier.toString(mod);
}
}
结果如下:
1
2
3
Constructors for com.example.demo.MyClass
public com.example.demo.MyClass([int i, int j, String s]) []
public com.example.demo.MyClass([Object t]) []
0x06 java反射对象创建
Java反射 - Java反射对象创建
我们可以使用反射动态创建类的对象。通过调用其中一个构造函数。
然后我们可以访问对象的字段的值,设置它们的值,并调用它们的方法。
有两种方法来创建对象:
  • 使用no-args构造函数
  • 使用带参数的构造函数
    无参数构造函数
    如果你有一个Class对象的引用,你可以创建一个对象该类对Class类使用newInstance()方法。
    此方法不使用参数,并且是等效的使用new运算符的类的no-args构造函数。
    1
    MyClass m  = myObject.newInstance();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.demo;

class MyClass {
public MyClass() {
System.out.println("called");
}
}

public class Test12 {
public static void main(String[] args) throws InstantiationException {
Class<MyClass> personClass = MyClass.class;
try {
MyClass p = personClass.newInstance();
System.out.println(p);
} catch (InstantiationException | IllegalAccessException e) {
System.out.println(e.getMessage());
}
}
}
结果如下:
1
2
called
com.example.demo.MyClass@2ff4acd0
带参数的构造函数
您可以通过调用特定的构造函数使用反射创建对象。它涉及两个步骤。
  • 获取构造函数的实例
  • 调用newInstance来调用它
    你可以得到这个构造函数的引用,如下所示:
    1
    Constructor<MyClass> cons  = myClass.getConstructor(int.class, String.class);
然后调用带有参数的newInstance()方法来创建一个对象。
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 com.example.demo;

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

class MyClass {
public MyClass(int i, String s) {
System.out.println("called");
System.out.println(i);
System.out.println(s);
}
}

public class Test12 {
public static void main(String[] args) throws InstantiationException {
Class<MyClass> myClass = MyClass.class;
try {
Constructor<MyClass> cons = myClass.getConstructor(int.class, String.class);
MyClass chris = cons.newInstance(1, "abc");
System.out.println(chris);
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
System.out.println(e.getMessage());
}
}
}
结果如下:
1
2
3
4
called
1
abc
com.example.demo.MyClass@2ff4acd0
调用方法
我们可以通过方法引用使用反射调用方法。
要调用方法,请调用方法引用的 invoke()方法。
它的第一个参数是它来自和的对象第二个参数是同一顺序中所有参数的varargs作为方法的声明。
在静态方法的情况下,我们只需要为第一个参数指定null。
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
package com.example.demo;

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

class MyClass {
public MyClass() {
}

public void setName(String n) {
System.out.println(n);
}
}

public class Test12 {
public static void main(String[] args) {
Class<MyClass> myClass = MyClass.class;
try {
MyClass p = myClass.newInstance();
Method setName = myClass.getMethod("setName", String.class);
setName.invoke(p, "abc");
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
| IllegalArgumentException | InvocationTargetException e) {
System.out.println(e.getMessage());
}
}
}
结果如下:
1
abc
0x08 java反射字段访问
Java反射 - Java反射字段访问
我们可以使用反射在两个步骤中获取或设置字段。
  • 获取字段的引用。
  • 要读取字段的值,请在字段上调用getXxx()方法,其中Xxx是字段的数据类型。
  • 要设置字段的值,请调用相应的setXxx()方法。
    以相同的方式访问静态和实例字段。
    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
    package com.example.demo;

    import java.lang.reflect.Field;

    class MyClass {
    public String name = "Unknown";

    public MyClass() {
    }

    public String toString() {
    return "name=" + this.name;
    }
    }

    public class Test12 {
    public static void main(String[] args) {
    Class<MyClass> ppClass = MyClass.class;
    try {
    MyClass p = ppClass.newInstance();
    Field name = ppClass.getField("name");
    String nameValue = (String) name.get(p);
    System.out.println("Current name is " + nameValue);
    name.set(p, "abc");
    nameValue = (String) name.get(p);
    System.out.println("New name is " + nameValue);
    } catch (InstantiationException | IllegalAccessException | NoSuchFieldException | SecurityException
    | IllegalArgumentException e) {
    System.out.println(e.getMessage());
    }
    }
    }
结果如下:
1
2
Current name is Unknown
New name is abc
绕过辅助功能检查
使用反射访问类的非可访问字段,方法和构造函数从 AccessibleObject 类调用 setAccessible(boolean flag)方法。
我们需要使用true参数调用此方法,以使该字段,方法和构造函数可访问。
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
package com.example.demo;

import java.lang.reflect.Field;

class MyClass {
private String name = "Unknown";

public MyClass() {
}

public String toString() {
return "name=" + this.name;
}
}

public class Test12 {
public static void main(String[] args) {
Class<MyClass> ppClass = MyClass.class;
try {
MyClass p = ppClass.newInstance();
Field name = ppClass.getDeclaredField("name");
name.setAccessible(true);
String nameValue = (String) name.get(p);
System.out.println("Current name is " + nameValue);
name.set(p, "abc");
nameValue = (String) name.get(p);
System.out.println("New name is " + nameValue);
} catch (InstantiationException | IllegalAccessException | NoSuchFieldException | SecurityException
| IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
结果如下:
1
2
Current name is Unknown
New name is abc
0x09 java数组反射
Java反射 - Java数组反射
我们可以使用Class类中的isArray()方法来检查类是否是数组。
我们可以创建一个数组,使用反射通过读取和修改其元素的值java.lang.reflect.Array类。
Array类的getLength()方法获取数组的长度。
Array类中的所有方法都是静态的。
要创建数组,请使用Array类中的重载静态方法newInstance()。
1
2
Object newInstance(Class<?> componentType,  int  arrayLength)
Object newInstance(Class<?> componentType, int... dimensions)
第一个方法根据指定的组件类型和数组长度创建一个数组。
第二个版本创建指定组件类型和尺寸的数组。
newInstance()方法的返回类型是Object,我们需要将它转换为实际的数组类型。
下面的代码创建一个长度为5的int数组。
1
int[] ids = (int[])Array.newInstance(int.class, 5);
下面的代码创建一个长度为5乘3的int数组。
1
int[][] matrix = (int[][])Array.newInstance(int.class, 5, 3);
以下代码显示了如何动态创建数组并操作其元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.demo;

import java.lang.reflect.Array;

public class Test12 {
public static void main(String[] args) {
try {
Object my = Array.newInstance(int.class, 2);

int n1 = Array.getInt(my, 0);
int n2 = Array.getInt(my, 1);
System.out.println("n1 = " + n1 + ",n2=" + n2);

Array.set(my, 0, 11);
Array.set(my, 1, 12);

n1=Array.getInt(my, 0);
n2=Array.getInt(my, 1);
System.out.println("n1 = " + n1 + ",n2=" + n2);
} catch (NegativeArraySizeException | IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
}
}
结果如下:
1
2
n1 = 0,n2=0
n1 = 11,n2=12
获取数组的维度
Java支持array数组。
类中的getComponentType()方法返回数组的元素类型的Class对象。
以下代码说明了如何获取数组的维度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.demo;

public class Test12 {
public static void main(String[] args) {
int[][][] intArray = new int[1][2][3];

System.out.println("int[][][] dimension is " + getArrayDimension(intArray));
}

public static int getArrayDimension(Object array) {
int dimension = 0;
Class<?> c = array.getClass();
if (!c.isArray()) {
throw new IllegalArgumentException("Object is not an array");
}
while (c.isArray()) {
dimension++;
c = c.getComponentType();
}
return dimension;
}
}
结果如下:
1
int[][][] dimension is 3
展开数组
Java数组是一个固定长度的数据结构。
要放大数组,我们可以创建一个更大尺寸的数组,并将旧数组元素复制到新数组元素。
以下代码显示如何使用反射展开数组。
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
package com.example.demo;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test12 {
public static void main(String[] args) {
int[] ids = new int[2];
System.out.println(ids.length);
System.out.println(Arrays.toString(ids));

ids = (int[]) expandBy(ids, 2);

ids[2] = 3;
System.out.println(ids.length);
System.out.println(Arrays.toString(ids));
}

public static Object expandBy(Object oldArray, int increment) {
Object newArray = null;
int oldLength = Array.getLength(oldArray);
int newLength = oldLength + increment;
Class<?> c = oldArray.getClass();
newArray = Array.newInstance(c.getComponentType(), newLength);
System.arraycopy(oldArray, 0, newArray, 0, oldLength);
return newArray;
}
}
结果如下:
1
2
3
4
2
[0, 0]
4
[0, 0, 3, 0]
0x10 参考链接
https://www.w3cschool.cn/java/java-array-reflection.html