• 【反射】Constructor类


    Constructor类中包含了构造方法定义的详细信息,可以使用Constructor类中提供的方法来获取构造方法的信息,下面我们先获取Constructor对象,再介绍如何使用Constructor类中的newInstance方法创建对象。

    一、准备工作

    在src/test/java目录的cn.horse.reflect.entity包下新建BaseEntity类、UserInfoEntity类;新建EntityAnnotation、InheritedEntityAnnotation、UserInfoEntityAnnotation注解

    BaseEntity类:

    1. package cn.horse.reflect.entity;
    2. @EntityAnnotation
    3. @InheritedEntityAnnotation
    4. public abstract class BaseEntity {
    5. @EntityAnnotation
    6. @InheritedEntityAnnotation
    7. public Long id;
    8. @InheritedEntityAnnotation
    9. public BaseEntity() { }
    10. @EntityAnnotation
    11. @InheritedEntityAnnotation
    12. public BaseEntity(Long id) {
    13. this.id = id;
    14. }
    15. @EntityAnnotation
    16. @InheritedEntityAnnotation
    17. public void setId(Long id) {
    18. this.id = id;
    19. }
    20. public Long getId() {
    21. return id;
    22. }
    23. }

    UserInfoEntity类:

    1. package cn.horse.reflect.entity;
    2. @UserInfoEntityAnnotation
    3. public class UserInfoEntity extends BaseEntity {
    4. @UserInfoEntityAnnotation
    5. public String name;
    6. @UserInfoEntityAnnotation
    7. private Integer age;
    8. @UserInfoEntityAnnotation
    9. private UserInfoEntity() {
    10. }
    11. @UserInfoEntityAnnotation
    12. public UserInfoEntity(Long id) {
    13. super(id);
    14. }
    15. @UserInfoEntityAnnotation
    16. public UserInfoEntity(Long id, String name, Integer age) {
    17. super(id);
    18. this.name = name;
    19. this.age = age;
    20. }
    21. public void setAge(Integer age) {
    22. this.age = age;
    23. }
    24. public Integer getAge() {
    25. return age;
    26. }
    27. private String getName() {
    28. return name;
    29. }
    30. private void check() { }
    31. @UserInfoEntityAnnotation
    32. @Override
    33. public void setId(Long id) {
    34. super.setId(id);
    35. }
    36. }

    EntityAnnotation注解:

    1. package cn.horse.reflect.entity;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. import static java.lang.annotation.ElementType.*;
    6. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    7. @Retention(RetentionPolicy.RUNTIME)
    8. public @interface EntityAnnotation {
    9. }

    InheritedEntityAnnotation注解:

    1. package cn.horse.reflect.entity;
    2. import java.lang.annotation.Inherited;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. import static java.lang.annotation.ElementType.*;
    7. import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
    8. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    9. @Retention(RetentionPolicy.RUNTIME)
    10. @Inherited
    11. public @interface InheritedEntityAnnotation {
    12. }

    UserInfoEntityAnnotation注解:

    1. package cn.horse.reflect.entity;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. import static java.lang.annotation.ElementType.*;
    6. import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
    7. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    8. @Retention(RetentionPolicy.RUNTIME)
    9. public @interface UserInfoEntityAnnotation {
    10. }

    二、获取Constructor对象

    在src/test/java目录的cn.horse.reflect包下新建GetConstructorInstanceTests测试类

    GetConstructorInstanceTests类:

    1. package cn.horse.reflect;
    2. import cn.horse.reflect.entity.UserInfoEntity;
    3. import org.junit.jupiter.api.Test;
    4. import java.lang.reflect.Constructor;
    5. import java.util.Arrays;
    6. import java.util.Collection;
    7. import java.util.List;
    8. import java.util.stream.Collectors;
    9. import static org.assertj.core.api.Assertions.assertThat;
    10. import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    11. public class GetConstructorInstanceTests {
    12. static final Class USER_INFO_ENTITY_CLASS = UserInfoEntity.class;
    13. @Test
    14. public void testGetConstructors() {
    15. // getConstructors 获取当前类中使用public定义的构造方法
    16. Collection constructorNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getConstructors()).map(Constructor::toString).collect(Collectors.toList());
    17. List expectedConstructorNameList = Arrays.asList("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
    18. assertThat(constructorNameList.size()).isEqualTo(expectedConstructorNameList.size());
    19. assertThat(constructorNameList).containsAll(expectedConstructorNameList);
    20. }
    21. @Test
    22. public void testGetConstructor() throws NoSuchMethodException {
    23. assertThatExceptionOfType(NoSuchMethodException.class).isThrownBy(() -> USER_INFO_ENTITY_CLASS.getConstructor());
    24. assertThat(USER_INFO_ENTITY_CLASS.getConstructor(Long.class)).isNotNull();
    25. assertThat(USER_INFO_ENTITY_CLASS.getConstructor(Long.class, String.class, Integer.class)).isNotNull();
    26. }
    27. @Test
    28. public void testGetDeclaredConstructors() {
    29. // getDeclaredConstructors 获取当前类中定义的所有构造方法
    30. Collection declaredConstructorNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructors()).map(Constructor::toString).collect(Collectors.toList());
    31. List expectedDeclaredConstructorNameList = Arrays.asList("private cn.horse.reflect.entity.UserInfoEntity()", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)", "public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
    32. assertThat(declaredConstructorNameList.size()).isEqualTo(expectedDeclaredConstructorNameList.size());
    33. assertThat(declaredConstructorNameList).containsAll(expectedDeclaredConstructorNameList);
    34. }
    35. @Test
    36. public void testGetDeclaredConstructor() throws NoSuchMethodException {
    37. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor()).isNotNull();
    38. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class)).isNotNull();
    39. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class)).isNotNull();
    40. }
    41. }

    单元测试方法介绍:

    testGetConstructors使用getConstructors方法获取当前类中使用public定义的构造方法

    testGetConstructor使用getConstructor方法获取当前类中使用public定义的指定构造方法(使用构造方法的参数类型进行匹配)

    testGetDeclaredConstructors使用getDeclaredConstructors方法获取当前类中定义的所有构造方法

    testGetDeclaredConstructor使用getDeclaredConstructor方法获取当前类中定义的指定构造方法(使用构造方法的参数类型进行匹配)

    三、Constructor类中方法的使用

    在src/test/java目录的cn.horse.reflect包下新建ConstructorInstanceMethodTests测试类

    ConstructorInstanceMethodTests类:

    1. package cn.horse.reflect;
    2. import cn.horse.reflect.entity.EntityAnnotation;
    3. import cn.horse.reflect.entity.InheritedEntityAnnotation;
    4. import cn.horse.reflect.entity.UserInfoEntity;
    5. import cn.horse.reflect.entity.UserInfoEntityAnnotation;
    6. import org.junit.jupiter.api.Test;
    7. import java.lang.annotation.Annotation;
    8. import java.lang.reflect.Constructor;
    9. import java.lang.reflect.InvocationTargetException;
    10. import java.lang.reflect.Modifier;
    11. import java.util.Arrays;
    12. import java.util.Collection;
    13. import java.util.List;
    14. import java.util.stream.Collectors;
    15. import static org.assertj.core.api.Assertions.assertThat;
    16. import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    17. public class ConstructorInstanceMethodTests {
    18. static final Class USER_INFO_ENTITY_CLASS = UserInfoEntity.class;
    19. @Test
    20. public void testGetDeclaringClass() throws NoSuchMethodException {
    21. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaringClass()).isEqualTo(UserInfoEntity.class);
    22. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getDeclaringClass()).isEqualTo(UserInfoEntity.class);
    23. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getDeclaringClass()).isEqualTo(UserInfoEntity.class);
    24. }
    25. @Test
    26. public void testGetName() throws NoSuchMethodException {
    27. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
    28. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
    29. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getName()).isEqualTo("cn.horse.reflect.entity.UserInfoEntity");
    30. }
    31. @Test
    32. public void testToString() throws NoSuchMethodException {
    33. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().toString()).isEqualTo("private cn.horse.reflect.entity.UserInfoEntity()");
    34. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).toString()).isEqualTo("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long)");
    35. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).toString()).isEqualTo("public cn.horse.reflect.entity.UserInfoEntity(java.lang.Long,java.lang.String,java.lang.Integer)");
    36. }
    37. @Test
    38. public void testGetModifiers() throws NoSuchMethodException {
    39. assertThat(Modifier.isPrivate(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getModifiers())).isTrue();
    40. assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getModifiers())).isTrue();
    41. assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getModifiers())).isTrue();
    42. }
    43. @Test
    44. public void testNoArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    45. // 获取private定义的无参数的构造方法创建对象
    46. Constructor noArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor();
    47. assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() -> noArgsConstructor.newInstance());
    48. noArgsConstructor.setAccessible(true);
    49. Object noArgsConstructorInstance = noArgsConstructor.newInstance();
    50. assertThat(noArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
    51. assertThat(((UserInfoEntity) noArgsConstructorInstance).getId()).isNull();
    52. }
    53. @Test
    54. public void testIdArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    55. // 获取public定义的参数只有id的构造方法创建对象
    56. Constructor idArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class);
    57. Object idArgsConstructorInstance = idArgsConstructor.newInstance(200L);
    58. assertThat(idArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
    59. assertThat(((UserInfoEntity) idArgsConstructorInstance).getId()).isEqualTo(200L);
    60. }
    61. @Test
    62. public void testAllArgsConstructorCreateInstance() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    63. // 获取public定义的参数包含id,name,age的构造方法创建对象
    64. Constructor allArgsConstructor = USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class);
    65. Object allArgsConstructorInstance = allArgsConstructor.newInstance(200L, "张三", 10);
    66. assertThat(allArgsConstructorInstance).isInstanceOf(USER_INFO_ENTITY_CLASS);
    67. assertThat(((UserInfoEntity) allArgsConstructorInstance).getId()).isEqualTo(200L);
    68. assertThat(((UserInfoEntity) allArgsConstructorInstance).name).isEqualTo("张三");
    69. assertThat(((UserInfoEntity) allArgsConstructorInstance).getAge()).isEqualTo(10);
    70. }
    71. @Test
    72. public void testNoArgsConstructorGetAnnotations() throws NoSuchMethodException {
    73. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    74. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    75. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    76. assertThat(annotationList).containsAll(expectedAnnotationList);
    77. }
    78. @Test
    79. public void testIdArgsConstructorGetAnnotations() throws NoSuchMethodException {
    80. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    81. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    82. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    83. assertThat(annotationList).containsAll(expectedAnnotationList);
    84. }
    85. @Test
    86. public void testAllArgsConstructorGetAnnotations() throws NoSuchMethodException {
    87. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    88. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    89. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    90. assertThat(annotationList).containsAll(expectedAnnotationList);
    91. }
    92. @Test
    93. public void testConstructorGetAnnotationsByType() throws NoSuchMethodException {
    94. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
    95. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    96. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    97. assertThat(annotationList).containsAll(expectedAnnotationList);
    98. }
    99. @Test
    100. public void testConstructorGetAnnotation() throws NoSuchMethodException {
    101. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getAnnotation(EntityAnnotation.class)).isNull();
    102. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getAnnotation(InheritedEntityAnnotation.class)).isNull();
    103. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
    104. }
    105. @Test
    106. public void testNoArgsConstructorGetDeclaredAnnotations() throws NoSuchMethodException {
    107. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    108. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    109. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    110. assertThat(annotationList).containsAll(expectedAnnotationList);
    111. }
    112. @Test
    113. public void testIdArgsConstructorGetDeclaredAnnotations() throws NoSuchMethodException {
    114. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class).getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    115. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    116. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    117. assertThat(annotationList).containsAll(expectedAnnotationList);
    118. }
    119. @Test
    120. public void testAllArgsConstructorGetDeclaredAnnotations() throws NoSuchMethodException {
    121. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
    122. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    123. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    124. assertThat(annotationList).containsAll(expectedAnnotationList);
    125. }
    126. @Test
    127. public void testConstructorGetDeclaredAnnotationsByType() throws NoSuchMethodException {
    128. Collectionextends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredConstructor(Long.class, String.class, Integer.class).getDeclaredAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
    129. Listextends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
    130. assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
    131. assertThat(annotationList).containsAll(expectedAnnotationList);
    132. }
    133. @Test
    134. public void testConstructorGetDeclaredAnnotation() throws NoSuchMethodException {
    135. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaredAnnotation(EntityAnnotation.class)).isNull();
    136. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNull();
    137. assertThat(USER_INFO_ENTITY_CLASS.getDeclaredConstructor().getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
    138. }
    139. }

    单元测试方法介绍:

    testGetDeclaringClass获取声明类的Class对象,getDeclaringClass方法获取到的Class对象是构造方法所在类的Class对象

    testGetName获取名称,getName方法获取到的名称是构造方法所在类的名称

    testToString转换成字符串,toString方法用于将构造方法对象转换成字符串

    testGetModifiers获取修饰符,使用getModifiers获取修饰符,并使用Modifier类提供的静态方法依次判断了是否使用了public、private、protected等修饰符

    testNoArgsConstructorCreateInstance使用无参数的构造方法创建对象,方法中首先获取了无参数的构造方法,直接使用newInstance创建对象会抛出IllegalAccessException异常,原因是构造方法使用了private修饰,这里使用setAccessible设置访问了访问全限后在使用newInstance创建对象就可以了

    testIdArgsConstructorCreateInstance使用id参数的构造方法创建对象

    testAllArgsConstructorCreateInstance使用所有参数的构造方法创建对象

    testGetAnnotations使用getAnnotations获取当前类的注解

    testGetAnnotationsByType使用getAnnotationsByType从当前类的注解中获取指定类型的注解

    testGetAnnotation使用getAnnotation从当前类的注解中获取指定类型的注解

    testGetDeclaredAnnotations使用getDeclaredAnnotations获取当前类的注解

    testGetDeclaredAnnotationsByType使用getDeclaredAnnotationsByType从当前类的注解中获取指定类型的注解

    testGetDeclaredAnnotation使用getDeclaredAnnotation从当前类的注解中获取指定类型的注解

  • 相关阅读:
    <哈希及模拟实现>——《C++高阶》
    C++新特性:智能指针
    为什么我发的视频播放量老涨不上去?
    springboot整合pi支付开发
    WhatsApp Business 与 Google My Business:它们的运作方式和不同之处
    springboot java高校在线办公自动化系统Vue
    思维题练习部分
    qmake $() $$() 区别
    【Linux】进程替换
    机器学习笔记之卡尔曼滤波(一)动态模型基本介绍
  • 原文地址:https://blog.csdn.net/m1729339749/article/details/133938856