【JavaAAR】Java注解和反射(5)
前言:
本文内容:动态创建对象执行方法、性能对比分析、获取泛型信息
推荐免费Java注解和反射讲解视频:【狂神说Java】注解和反射_哔哩哔哩_bilibili
动态创建对象执行方法
有了Class对象,能做什么
- 创建类的对象:调用Class对象的newInstance()方法:
- 类必须有一个无参数的构造器。
- 类的构造器的访问权限需要足够。
思考:难道没有无参的构造器就不能创建对象了吗?只要操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。
- 步骤如下:
- 通过Class类的
getDeclaredConstructor(Class...parameterTypes
取得本类的指定形参类型的构造器。 - 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
- 通过Constructor实例化对象。
- 通过Class类的
调用指定的方法
通过反射,调用类中的方法,通过Method类完成。
-
通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
-
之后使用Object invoke(Object obj,Object[]args)进行调用,并向方法中传递要设置的obj对象的参数信息。
调用指定的方法:
Object invoke(Object obj,Object… args)
- Object对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[]args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显示调用方法对象的
setAccessible(true)
方法,将可访问private的方法
setAccessible
-
Method和Field、Constructor对象都有setAccessible()方法。
-
setAccessible作用是启动和禁用访问安全检查的开关。
-
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
- 提高反射的效率,如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true
- 使原本无法访问的私有乘员也可以访问
-
参数值为false则指示反射的对象应该实施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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package com.jokerdig.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author Joker大雄
* @data 2021/9/10 - 19:06
**/
//动态的创建对象,通过反射
public class Demo07 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("com.jokerdig.reflection.User");
//构造一个对象
User user =(User) c1.newInstance();//调用无参构造器(过时)
System.out.println(user);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, String.class, int.class);
User user1 =(User) constructor.newInstance("张三", "123", 20);
System.out.println(user1);
//通过反射调用方法
User user3 =(User) c1.newInstance();//调用无参构造器
//通过反射获取方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke:激活
//用法:(对象,"方法的值")
setName.invoke(user3,"张三");
System.out.println(user3.getName());
//通过反射操作属性
User user4 =(User) c1.newInstance();//调用无参构造器
Field name =c1.getDeclaredField("name");
//关掉权限检测,来访问私有属性
name.setAccessible(true);//关闭检测,默认为false
name.set(user4,"张三2");
System.out.println(user4.getName());
}
}
性能对比分析
1 | package com.jokerdig.reflection; |
获取泛型信息
反射操作泛型
- Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题;但是,一旦编译完成,所有和泛型有关的类型全部擦除。
- 为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
常用的类型
-
ParameterizedType:表示一种参数化类型,比如
Collection<String>
-
GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
-
TypeVarable:是各种类型变量的公共父接口
-
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
41
42
43
44
45
46package com.jokerdig.reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* @author Joker大雄
* @data 2021/9/10 - 19:58
**/
//通过反射获取泛型
public class Demo09 {
public void test1(Map<String,User> map, List<User> list){
System.out.println("test1");
}
public Map<String,User> test2(){
System.out.println("test2");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Demo09.class.getMethod("test1", Map.class,List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(" "+genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actual =((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type type : actual) {
System.out.println(type);
}
}
}
method = Demo09.class.getMethod("test2",null);
Type genericReturnType=method.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualType =((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type type : actualType) {
System.out.println(type);
}
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hey,Joker!
评论
ValineTwikoo