Day8 反射机制 2
uwupu 啦啦啦啦啦

Java Reflection 反射机制2

获取运行时类的对象的属性

Class类的方法

方法名 介绍 参数
getName() 获得类的全名,包括包。如:com.uwupu.User
getSimpleName() 获得类的名字。如:User
getFields() 获取类的public属性。
getDeclaredFields() 获得类的所有属性。
getDeclaredField(param) 通过名字获得类的属性 属性的名字
getDeclaredConstructors() 获得类的所有的构造器
getConstructors() 获得类的public的构造器
getConstructor(param) 通过构造器的参数获得类的构造器 构造器的参数

代码

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
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("Demo2_Reflection.User");//引用一个之前用过的类

//获得类的名字
System.out.println(c1.getName());//获得包名和类名
System.out.println(c1.getSimpleName());//获得类名
/*
Demo2_Reflection.User
User
*/

//获得类的属性
System.out.println("------------------");
Field[] fields = c1.getFields();//仅为public的属性
for (Field f : fields){
System.out.println(f);
}
System.out.println("------------------");
fields = c1.getDeclaredFields();//全部的属性
for (Field f : fields){
System.out.println(f);
}
/*
------------------
public int Demo2_Reflection.User.length
------------------
private java.lang.String Demo2_Reflection.User.name
private int Demo2_Reflection.User.id
private int Demo2_Reflection.User.age
public int Demo2_Reflection.User.length
*/

//获得指定属性
Field name = c1.getDeclaredField("name");
System.out.println(name);//private java.lang.String Demo2_Reflection.User.name

//获得类的方法
Method[] methods = c1.getMethods();//获得本类及其父类的public方法。
for (Method method : methods) {
System.out.println("getMethods:"+method);
}
methods = c1.getDeclaredMethods();//获得本类及其父类的所有方法
for (Method method : methods) {
System.out.println("getDeclaredMethods:"+method);
}

//获得指定方法
Method getMethod = c1.getMethod("getName");
Method setMethod = c1.getMethod("setName",String.class);//后面的参数用于筛选方法重载时的多个方法。
System.out.println(getMethod);//public java.lang.String Demo2_Reflection.User.getName()
System.out.println(setMethod);//public void Demo2_Reflection.User.setName(java.lang.String)

//获得指定的构造器
Constructor[] constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
/*
public Demo2_Reflection.User()
public Demo2_Reflection.User(java.lang.String,int,int)
*/
Constructor constructor = c1.getConstructor(String.class,int.class,int.class);
System.out.println(constructor);//public Demo2_Reflection.User(java.lang.String,int,int)
}
}

对Class对象进行一些操作

创建类的对象:

方法1:

调用Class对象的newInstance()方法。

  • 类必须有一个无参构造器;
  • 需要足够的类的构造器访问权限。

代码:

1
2
3
4
5
6
7
8
9
10
public class Demo8_通过Class对象对类进行一些操作 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//获得Class对象
Class c1 = Class.forName("Demo2_Reflection.User");
//构造一个对象
User user = (User)c1.newInstance();//本质上调用了类的无参构造器。若没有无参构造器,会报错。
System.out.println(user);
//User{name='null', id=0, age=0}
}
}

方法2:

1
2
3
4
5
6
7
8
9
10
11
public class Demo8_通过Class对象对类进行一些操作 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//获得Class对象
Class c1 = Class.forName("Demo2_Reflection.User");
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 = (User) constructor.newInstance("张三",1,22);
System.out.println(user2);
//User{name='张三', id=1, age=22}
}
}

通过反射操作方法

Invoke

  • 可以操作方法,参数1为操作的对象,后面的参数为方法的参数。

  • 返回值为原方法的返回值。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo8_通过Class对象对类进行一些操作 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//获得Class对象
Class c1 = Class.forName("Demo2_Reflection.User");
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 = (User) constructor.newInstance("张三",1,22);
System.out.println(user2);

//通过反射调用普通方法

//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName",String.class);
setName.invoke(user2,"李四");
System.out.println(user2);
}
}
1
2
User{name='张三', id=1, age=22}
User{name='李四', id=1, age=22}

通过反射操作属性

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Demo8_通过Class对象对类进行一些操作 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("Demo2_Reflection.User");

//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 = (User) constructor.newInstance("张三",1,22);
System.out.println(user2);

//通过反射操作属性
//不能直接操作私有属性,通过setAccessible方法关掉权限监测。
Field name = c1.getDeclaredField("name");
name.setAccessible(true);//关掉权限监测
name.set(user2,"王五");//直接操作权限不够 name属性为private
System.out.println(user2);

}
}

1
2
User{name='李四', id=1, age=22}
User{name='王五', id=1, age=22}

注意

  • 若要”使用Field的set方法操作属性“或“使用invoke方法操作原方法”,若属性或方法用private修饰,则不能直接操作,需要用setAccessible(true)方法关掉权限监测,才可直接操作。

setAccessible

  • Method、Field和Constructor对象都有setAccessible()方法;
  • **setAccessible**作用是启动和禁用访问安全检查的开关。
  • 参数为true表示关闭反射对象访问检查。默认为false。
    • 可以提高反射效率。若代码中必须使用反射,且该句代码需要频繁地被调用,请一定设置为true。

获取泛型信息

Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题。一旦编译完成,所有和泛型有关的类型全部擦除。

为了通过反射操作这些类型,Java新增了集中类型来代表不能归一到Class类中的类型但是又和原始类型齐名的类型。

类型名 描述
ParameterizedType 表示一种参数化类型,如Collection<String>
GenericArrayType 表示一种元素类型是参数化类型或者类型变量的数组类型。
TypeVariable 是各种类型变量的公共父接口。
WildcardType 代表一种通配符类型表达式。

代码:

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
public class Test9 {
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test9.class.getMethod("test01",Map.class,List.class);

//获得参数是泛型
//Generic 泛型
Type[] types = method.getGenericParameterTypes();//获得参数类型列表
for (Type type : types){
System.out.println("# "+type);
if(type instanceof ParameterizedType){
Type[] type2 =((ParameterizedType) type).getActualTypeArguments();//获得真实参数信息 获得参数的泛型参数列表
for (Type type3 :type2){
System.out.println(type3);
}
}
}


System.out.println("--------------------------------");

//获得返回值是泛型的参数
method = Test9.class.getMethod("test02");
Type returnType = method.getGenericReturnType();
System.out.println("# "+returnType);
if(returnType instanceof ParameterizedType){
Type[] type2 =((ParameterizedType) returnType).getActualTypeArguments();//获得真实参数信息 获得参数的泛型参数列表
for (Type type3 :type2){
System.out.println(type3);
}
}

}
}

获取注解信息

ORM

  • Object relationship Mapping -> 对象关系映射

image

代码

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
public class Demo10_通过反射获得注解 {
public static void main(String[] args) throws Exception {
//获取类
Class c1 = Class.forName("MyClass");

//获取类的注解的值
MyAnnotation classAnnotation = (MyAnnotation) c1.getAnnotation(MyAnnotation.class);//获取注解对象
System.out.println(classAnnotation);//输出
System.out.println(
"id: " + classAnnotation.id() +
" name: " +classAnnotation.name()
);//获取注解的值

//获取属性的注解的值
Field field = c1.getField("id");
MyAnnotation myAnnoation = field.getAnnotation(MyAnnotation.class);
System.out.println(myAnnoation);
System.out.println(
"id: " + myAnnoation.id() +
" name: " +myAnnoation.name()
);

//获取方法的注解的值
Method method = c1.getMethod("int2String", int.class);
MyAnnotation methodAnnoation = method.getAnnotation(MyAnnotation.class);
System.out.println(methodAnnoation);
System.out.println(
"id: " + methodAnnoation.id() +
" name: " +methodAnnoation.name()
);

}
}

//一个类
@MyAnnotation(name = "MyClass",id = 1)
class MyClass{
@MyAnnotation(name = "id",id = 2)
public int id;//一个属性

//一个方法
@MyAnnotation(name = "int2String",id = 3)
public String int2String(int value){
return String.valueOf(value);
}
}

//声明注解

//一个Target可以是属性,类或方法的注解
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String name();
int id();
}

1
2
3
4
5
6
@MyAnnoation(name=MyClass, id=1)
id: 1 name: MyClass
@MyAnnoation(name=id, id=2)
id: 2 name: id
@MyAnnoation(name=int2String, id=3)
id: 3 name: int2String
 评论