反射是Java的特征之一,允许在程序运行时获取自身的信息,并且可以操作类或对象的内部属性。

为什么需要反射

  1. 提高程序的灵活度
    • 在平常开发者,由于有访问修饰符(public,default,protected,private)的限制,很多时候我们不能访问或者修改某些类的某些实现,这个时候反射就可以帮着我们达到这个目的。比如,通过ScrollView的mScroller字段获取对应的OverScroller对象,用来判断ScrollView的滚动状态;
    • 根据不同的配置加载不同的类或对象
  2. 屏蔽实现的细节,让使用者更加方便
    • 组件化中,下层组件提供接口Inter,上层组件B提供具体实现屏蔽,对外提供实现类全类名,上层组件C就可以根据该全类名通过反射生成对应的Inter实例并转化为Inter类型,来调用接口方法。这样组件C不用知道B中的具体实现,直接使用即可。

反射主要功能

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 在运行时调用任意一个对象的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 在运行时获取泛型信息;
  • 在运行时处理注解;
  • 生成动态代理;

    反射缺点

  1. 反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象
  2. 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题

反射基本应用

测试代码

Parent.java

  1. package com.bujian.reflects.model;
  2. public class Parent {
  3. String defaultParentFiled;
  4. public String publicParentFiled;
  5. private String privateParentFiled;
  6. protected String protectedParentFiled;
  7. public Parent() {
  8. }
  9. public Parent(String defaultParentFiled) {
  10. this.defaultParentFiled = defaultParentFiled;
  11. }
  12. Parent(String defaultParentFiled, String protectedParentFiled) {
  13. this.defaultParentFiled = defaultParentFiled;
  14. this.protectedParentFiled = protectedParentFiled;
  15. }
  16. protected Parent(String defaultParentFiled, String protectedParentFiled, String privateParentFiled) {
  17. this.defaultParentFiled = defaultParentFiled;
  18. this.protectedParentFiled = protectedParentFiled;
  19. this.privateParentFiled = privateParentFiled;
  20. }
  21. private Parent(String defaultParentFiled, String protectedParentFiled, String privateParentFiled, String publicParentFiled) {
  22. this.defaultParentFiled = defaultParentFiled;
  23. this.protectedParentFiled = protectedParentFiled;
  24. this.privateParentFiled = privateParentFiled;
  25. this.publicParentFiled = publicParentFiled;
  26. }
  27. @Override
  28. public String toString() {
  29. return "Parent{" +
  30. "defaultParentFiled='" + defaultParentFiled + '\'' +
  31. '}';
  32. }
  33. public void publicParentMethod() {
  34. System.out.println("publicParentMethod");
  35. }
  36. void defaultParentMethod() {
  37. System.out.println("defaultParentMethod");
  38. }
  39. protected void protectedParentMethod() {
  40. System.out.println("protectedParentMethod");
  41. }
  42. private void privateParentMethod() {
  43. System.out.println("privateParentMethod");
  44. }
  45. }

Child.java

  1. package com.bujian.reflects.model;
  2. /**
  3. * 父类
  4. */
  5. public class Child extends Parent {
  6. String defaultChildFiled;
  7. public String publicChildFiled;
  8. private String privateChildFiled;
  9. protected String protectedChildFiled;
  10. public Child() {
  11. }
  12. public Child(String defaultChildFiled) {
  13. this.defaultChildFiled = defaultChildFiled;
  14. }
  15. Child(String defaultChildFiled, String protectedChildFiled) {
  16. this.defaultChildFiled = defaultChildFiled;
  17. this.protectedChildFiled = protectedChildFiled;
  18. }
  19. protected Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled) {
  20. this.defaultChildFiled = defaultChildFiled;
  21. this.protectedChildFiled = protectedChildFiled;
  22. this.privateChildFiled = privateChildFiled;
  23. }
  24. private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled) {
  25. this.defaultChildFiled = defaultChildFiled;
  26. this.protectedChildFiled = protectedChildFiled;
  27. this.privateChildFiled = privateChildFiled;
  28. this.publicChildFiled = publicChildFiled;
  29. }
  30. public void publicChildMethod() {
  31. System.out.println("publicChildMethod");
  32. }
  33. public void defaultChildMethod() {
  34. System.out.println("defaultChildMethod");
  35. }
  36. protected void protectedChildMethod() {
  37. System.out.println("protectedChildMethod");
  38. }
  39. private void privateChildMethod() {
  40. System.out.println("privateChildMethod");
  41. }
  42. @Override
  43. public String toString() {
  44. return "Child{" +
  45. "defaultChildFiled='" + defaultChildFiled + '\'' +
  46. '}';
  47. }
  48. // 非静态内部类
  49. public class InnerChild {
  50. public InnerChild() {
  51. }
  52. }
  53. }

获取Class对象

反射通过获取Class对象进而获取相关类的所有信息。Class获取的方式有3种:

  1. 使用Class.forName方法。例如,获取String的Class对象:

    1. Class<?> stringClass = Class.forName("java.lang.String");
  2. 通过类型获取

    1. Class<?> intClass = int.class;
    2. Class<?> integerClass = Integer.class;
  3. 通过对象的getClass方法获取

    1. Class<?> stringClass = "".getClass();

    判断是否为某个类实例

  4. isAssignableFrom(Class<?> cls):该类是否是参数cls自身或超集

    1. public boolean isAssignableFrom(Class<?> cls) {
    2. if (this == cls) {
    3. return true; // Can always assign to things of the same type.
    4. } else if (this == Object.class) {
    5. // Object不是基本类型的父类或父接口
    6. return !cls.isPrimitive();
    7. } else if (isArray()) {
    8. // componentType表示的是数组元素的具体类型
    9. return cls.isArray() && componentType.isAssignableFrom(cls.componentType);
    10. } else if (isInterface()) {
    11. // 参数是否实现了该接口
    12. Object[] iftable = cls.ifTable;
    13. if (iftable != null) {
    14. for (int i = 0; i < iftable.length; i += 2) {
    15. if (iftable[i] == this) {
    16. return true;
    17. }
    18. }
    19. }
    20. return false;
    21. } else {
    22. if (!cls.isInterface()) {
    23. for (cls = cls.superClass; cls != null; cls = cls.superClass) {
    24. if (cls == this) {
    25. return true;
    26. }
    27. }
    28. }
    29. return false;
    30. }
    31. }

    实例:

    1. Class<?> stringClass = Class.forName("java.lang.String");
    2. boolean assignableFrom = stringClass.isAssignableFrom(Object.class); // false
    3. boolean assignable = Object.class.isAssignableFrom(stringClass); // true
    4. boolean intAssignable = Object.class.isAssignableFrom(int.class); // false
  5. isInstance(Object obj):是否是obj的超集,内部实现是isAssignableFrom(Class<?> cls)

    1. public boolean isInstance(Object obj) {
    2. if (obj == null) {
    3. return false;
    4. }
    5. return isAssignableFrom(obj.getClass());
    6. }

    示例:

    1. boolean isInstance1 = stringClass.isInstance(new Object()); // false
    2. boolean isInstance2 = Object.class.isInstance(""); // true
    3. boolean isInstance3 = Object.class.isInstance((int)2); // true,注意,这里将int自动装箱成为了Integer
  6. getComponentType():获取数组元素类型

    1. int[] ints = new int[2];
    2. Class<? extends int[]> intsClass = ints.getClass();
    3. Class<?> componentType = intsClass.getComponentType(); // int
    4. Class<?> componentType1 = new String[2].getClass().getComponentType(); // class java.lang.String

    创建实例

    getConstructor(Class<?>… parameterTypes) : Constructor

    获取访问修饰符为public的构造方法。如果有多个public构造器,通过方法参数类型(parameterTypes)来区分想要调用哪一个。

注意:如果class表示的是一个非静态内部类,那么外层类将作为第一个参数传入

  1. Class<? extends Child> childClass = Child.class;
  2. Constructor<? extends Child> childClassConstructor = childClass.getConstructor();
  3. Child child = childClassConstructor.newInstance();
  4. // 方法参数类型需要一一对应,否则会报IllegalArgumentException异常
  5. // java.lang.IllegalArgumentException: Wrong number of arguments; expected 0, got 1
  6. // child = childClassConstructor.newInstance("defaultString");
  7. System.out.println(child); // Child{defaultChildFiled='null'}
  8. childClassConstructor = childClass.getConstructor(String.class);
  9. child = childClassConstructor.newInstance("defaultString");
  10. System.out.println(child); // Child{defaultChildFiled='defaultString'}
  11. // 对于非静态内部类,外部类作为第一个参数传入
  12. Class<Child.InnerChild> innerChildClass = Child.InnerChild.class;
  13. // 报异常:java.lang.NoSuchMethodException: <init> []
  14. // Constructor<Child.InnerChild> innerChildConstructor = innerChildClass.getConstructor();
  15. // 正确写法:Child.class作为第一个参数
  16. Constructor<Child.InnerChild> innerChildConstructor = innerChildClass.getConstructor(Child.class);
  17. System.out.println(innerChildConstructor.getName());

getConstructors() : Constructor<?>[]

返回所有声明为public的构造器。返回值是一个数组,假设数组长度为0,表示这个类不存在

返回值数组长度为0的情况:

  1. 该类不存在public的构造器
  2. 该类是基本类型、数组类型或void
    1. Constructor<?>[] constructors = childClass.getConstructors();
    2. Arrays.stream(constructors)
    3. .filter(Objects::nonNull)
    4. .forEach(c -> System.out.println(c.toString()));
    打印结果:

    public com.bujian.reflects.model.Child()
    public com.bujian.reflects.model.Child(java.lang.String)

getDeclaredConstructor(Class<?>… parameterTypes) : Constructor

获取Class对应类的构造方法。如果有多个public构造器,通过方法参数类型(parameterTypes)来区分想要调用哪一个。

注意:如果class表示的是一个非静态内部类,那么外层类将作为第一个参数传入
注意:如果通过非public构造器创建实例,需要调用setAccessible(true)方法,表示忽略Java语言访问限制符检查,否则报IllegalAccessException异常
**

  1. // private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled)
  2. Constructor<? extends Child> constructor = childClass.getDeclaredConstructor(String.class, String.class, String.class, String.class);
  3. System.out.println(constructor.toString());
  4. //
  5. Child declareChild = constructor.newInstance("defaultChildFiled", "protectedChildFiled", "privateChildFiled", "publicChildFiled");
  6. System.out.println(declareChild);

private com.bujian.reflects.model.Child(java.lang.String,java.lang.String,java.lang.String,java.lang.String)

// 缺少访问限制处理策略 java.lang.IllegalAccessException: Class java.lang.Class cannot access private method void com.bujian.reflects.model.Child.(java.lang.String, java.lang.String, java.lang.String, java.lang.String) of class java.lang.Class

  1. // private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled)
  2. Constructor<? extends Child> constructor = childClass.getDeclaredConstructor(String.class, String.class, String.class, String.class);
  3. System.out.println(constructor.toString());
  4. constructor.setAccessible(true);
  5. Child declareChild = constructor.newInstance("defaultChildFiled", "protectedChildFiled", "privateChildFiled", "publicChildFiled");
  6. System.out.println(declareChild);

private com.bujian.reflects.model.Child(java.lang.String,java.lang.String,java.lang.String,java.lang.String)

Child{defaultChildFiled=’defaultChildFiled’}

getDeclaredConstructors() : Constructor<?>[]

获取Class对应类的所有构造方法

  1. Constructor<?>[] declaredConstructors = childClass.getDeclaredConstructors();
  2. Arrays.stream(declaredConstructors)
  3. .filter(Objects::nonNull)
  4. .forEach(c -> {
  5. c.setAccessible(true);
  6. System.out.println(c.toString());
  7. });

public com.bujian.reflects.model.Child() public com.bujian.reflects.model.Child(java.lang.String) com.bujian.reflects.model.Child(java.lang.String,java.lang.String) protected com.bujian.reflects.model.Child(java.lang.String,java.lang.String,java.lang.String) private com.bujian.reflects.model.Child(java.lang.String,java.lang.String,java.lang.String,java.lang.String)

getEnclosingConstructor() : Constructor<?>

如果class对应的类是声明在某个类的构造器中,那么该class的该方法返回包裹其类声明的构造器的Constructor实例。例如:

  1. package com.bujian.reflects.model;
  2. public class OuterCloser {
  3. public Object mEncloser;
  4. public OuterCloser() {
  5. class Encloser {
  6. }
  7. mEncloser = new Encloser();
  8. }
  9. }
  10. // 测试
  11. OuterCloser outerCloser = new OuterCloser();
  12. Class<?> aClass = outerCloser.mEncloser.getClass();
  13. Constructor<?> enclosingConstructor = aClass.getEnclosingConstructor();
  14. System.out.println(enclosingConstructor);

public com.bujian.reflects.model.OuterCloser()

获取方法

getMethod(String name, Class<?>… parameterTypes) : Method

获取public修饰符限制的方法。name表示方法名,parameterTypes表示方法参数。

注意:

  1. 如果没有参数,什么都不用填;
  2. 如果在本类找不到对应的方法,会向上其父类和接口递归查找;
  3. name参数不能传递<init><clinit>,否则会报NoSuchMethodException异常

getMethods() : Method[]

获取自身或超级的所有public方法

getDeclaredMethod(String name, Class<?>… parameterTypes) :Method

获取自身的public方法

getDeclaredMethods() : Method[]

获取自身的所有方法

getEnclosingMethod() :Method

如果该类声明在一个方法中,该方法返回该类的所在方法的Method对象

获取Filed

getField(String name) : Field

getFields() : Field[]

getDeclaredField(String name) : Field

getDeclaredFields() : Field[]

获取注解信息(只能获取到运行时注解)

getAnnotation(Class annotationClass) : A

获取Class自身以及继承而来的运行时注解

getAnnotations() :Annotation[]

获取自身全部的注解

getDeclaredAnnotation(Class annotationClass) : A

获取Class自身的注解

getDeclaredAnnotations() :Annotation[]

获取自身全部的注解

isAnnotation() : boolean

是否是一个注解

isAnnotationPresent(Class<? extends Annotation> annotationClass) : boolean

是否被annotationClass注解标注

getAnnotationsByType(Class annotationClass) :A[]

获取与该元素相关联的注解(包括继承而来的)。与getAnnotation不一样的地方在于,如果该元素同时被一个注解标注N次,该方法会返回N次相同注解,getAnnotation只会返回一个。

getDeclaredAnnotationsByType(Class annotationClass) :A[]

获取与该元素相关联的注解。与getAnnotation不一样的地方在于,如果该元素同时被一个注解标注N次,该方法会返回N次相同注解,getAnnotation只会返回一个。

反射注解使用实例

com.bujian.reflects.anno.RuntimeAnno 在运行期有效,不具备继承性

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.TYPE)
  3. public @interface RuntimeAnno {
  4. }

com.bujian.reflects.anno.RuntimeInheritAnno 在运行期有效,具备继承性

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.TYPE)
  3. @Inherited // 具备继承性。例如,AnnotationModel有该注解标注,那么其子类AnnotationChildModel也可以使用该注解
  4. public @interface RuntimeInheritAnno {
  5. }

com.bujian.reflects.anno.ClassAnno 仅在编译期有效,不具备继承性

  1. @Retention(RetentionPolicy.CLASS)
  2. @Target(ElementType.TYPE)
  3. public @interface ClassAnno {
  4. }

com.bujian.reflects.anno.ClassInheritAnno 仅在编译期有效,具备继承性

  1. @Retention(RetentionPolicy.CLASS)
  2. @Target(ElementType.TYPE)
  3. public @interface ClassInheritAnno {
  4. }

com.bujian.reflects.model.AnnotationModel

  1. @RuntimeAnno
  2. @RuntimeInheritAnno
  3. @ClassAnno
  4. @ClassInheritAnno
  5. public class AnnotationModel {
  6. }

com.bujian.reflects.model.AnnotationChildModel

  1. public class AnnotationChildModel {
  2. }
  1. System.out.println(AnnotationModel.class.getAnnotation(ClassAnno.class));
  2. System.out.println(AnnotationChildModel.class.getAnnotation(ClassAnno.class));
  3. System.out.println(AnnotationModel.class.getDeclaredAnnotation(ClassAnno.class));
  4. System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(ClassAnno.class));
  5. System.out.println(AnnotationModel.class.getAnnotation(ClassInheritAnno.class));
  6. System.out.println(AnnotationChildModel.class.getAnnotation(ClassInheritAnno.class));
  7. System.out.println(AnnotationModel.class.getDeclaredAnnotation(ClassInheritAnno.class));
  8. System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(ClassInheritAnno.class));
  9. System.out.println(AnnotationModel.class.getAnnotation(RuntimeAnno.class));
  10. System.out.println(AnnotationChildModel.class.getAnnotation(RuntimeAnno.class));
  11. System.out.println(AnnotationModel.class.getDeclaredAnnotation(RuntimeAnno.class));
  12. System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(RuntimeAnno.class));
  13. System.out.println(AnnotationModel.class.getAnnotation(RuntimeInheritAnno.class));
  14. System.out.println(AnnotationChildModel.class.getAnnotation(RuntimeInheritAnno.class));
  15. System.out.println(AnnotationModel.class.getDeclaredAnnotation(RuntimeInheritAnno.class));
  16. System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(RuntimeInheritAnno.class));

null // 获取不到非运行期注解 null // 获取不到非运行期注解 null // 获取不到非运行期注解 null // 获取不到非运行期注解

null // 获取不到非运行期注解 null // 获取不到非运行期注解 null // 获取不到非运行期注解 null // 获取不到非运行期注解

@com.bujian.reflects.anno.RuntimeAnno() // 获取到运行时注解 null // 子类不能获取到运行时不可继承注解 @com.bujian.reflects.anno.RuntimeAnno() // 获取到运行时注解 null // 子类不能获取到运行时不可继承注解

@com.bujian.reflects.anno.RuntimeInheritAnno() // getAnnotation:获取到运行时注解 @com.bujian.reflects.anno.RuntimeInheritAnno() // getAnnotation:子类能获取到父类的运行时可继承注解 @com.bujian.reflects.anno.RuntimeInheritAnno() // getDeclaredAnnotation:获取到运行时注解 null // getDeclaredAnnotation:子类不能获取到父类的运行时可继承注解

getAnnotationsByType使用示例

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface RepeatableModels {
  4. RepeatableModel[] value();
  5. }
  6. @Target(ElementType.TYPE)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. // 当我们需要重复使用某个注解来达到相同注解表现出不同的形式时,可以使用Repeatable注解
  9. // Repeatable括号内的注解相当于用来该注解(RepeatableModel)的内容容器
  10. @Repeatable(RepeatableModels.class)
  11. public @interface RepeatableModel {
  12. String repeatableString() default "repeat";
  13. }
  14. @RepeatableModel(repeatableString = "bujian")
  15. @RepeatableModel(repeatableString = "oliver")
  16. @RepeatableModel(repeatableString = "coco")
  17. public class RepeatContent {
  18. }
  19. // 使用
  20. Annotation[] annotations = RepeatContent.class.getAnnotations();
  21. for (Annotation annotation : annotations) {
  22. System.out.println(annotation);
  23. }
  24. RepeatableModel[] models = RepeatContent.class.getAnnotationsByType(RepeatableModel.class);
  25. for (RepeatableModel model : models) {
  26. System.out.println(model);
  27. System.out.println(model.repeatableString());
  28. }

@com.bujian.reflects.anno.RepeatableModels(value=[@com.bujian.reflects.anno.RepeatableModel(repeatableString=bujian), @com.bujian.reflects.anno.RepeatableModel(repeatableString=oliver), @com.bujian.reflects.anno.RepeatableModel(repeatableString=coco)])

@com.bujian.reflects.anno.RepeatableModel(repeatableString=bujian) bujian @com.bujian.reflects.anno.RepeatableModel(repeatableString=oliver) oliver @com.bujian.reflects.anno.RepeatableModel(repeatableString=coco) coco

对于使用多个相同注解的元素调用getAnnotations()之后,会将这些相同注解打包成为数组作为一个元素返回。所以如果不通过getAnnotationsByType获取的话,也可以通过遍历数组获取:

  1. Annotation[] annotations = RepeatContent.class.getAnnotations();
  2. RepeatableModels repeatableModels = (RepeatableModels) annotations[0];
  3. for (Annotation annotation : repeatableModels.value()) {
  4. System.out.println(annotation);
  5. }

@com.bujian.reflects.anno.RepeatableModel(repeatableString=oliver) @com.bujian.reflects.anno.RepeatableModel(repeatableString=coco) @com.bujian.reflects.anno.RepeatableModel(repeatableString=bujian)

Class常用方法

isLocalClass() : boolean

返回true表示这是一个本地类。源码如下:

  1. public boolean isLocalClass() {
  2. return (getEnclosingMethod() != null || getEnclosingConstructor() != null)
  3. && !isAnonymousClass();
  4. }

通过源码可以知道,本地类就是一个定义在方法中或构造方法中的非匿名类。

  1. package com.bujian.reflects.model;
  2. public class LocalClass {
  3. public Object localInMethod;
  4. public Object localAnonymousInMethod;
  5. public Object localInConstructor;
  6. public Object localAnonymousInConstructor;
  7. public Object localAnonymous = new Predicate<String>() {
  8. @Override
  9. public boolean test(String s) {
  10. return false;
  11. }
  12. };
  13. public LocalClass() {
  14. class LocalInConstructor {
  15. }
  16. this.localInConstructor = new LocalInConstructor();
  17. this.localAnonymousInConstructor = new Predicate<String>() {
  18. @Override
  19. public boolean test(String s) {
  20. return false;
  21. }
  22. };
  23. }
  24. public void testLocalInMethod() {
  25. class LocalInMethod {
  26. }
  27. this.localInMethod = new LocalInMethod();
  28. this.localAnonymousInMethod = new Predicate<String>() {
  29. @Override
  30. public boolean test(String s) {
  31. return false;
  32. }
  33. };
  34. }
  35. public class LocalInner {
  36. }
  37. }

测试代码:

  1. LocalClass localClass = new LocalClass();
  2. localClass.testLocalInMethod();
  3. System.out.println(localClass.localInConstructor.getClass().isLocalClass());
  4. System.out.println(localClass.localAnonymousInConstructor.getClass().isLocalClass());
  5. System.out.println(localClass.localInMethod.getClass().isLocalClass());
  6. System.out.println(localClass.localAnonymousInMethod.getClass().isLocalClass());
  7. System.out.println(LocalClass.LocalInner.class.isLocalClass());

true false true false false

isAnonymousClass() : boolean

返回true表示这是一个匿名类。该方法是一个本地方法。

  1. @FastNative
  2. public native boolean isAnonymousClass();

上述测试代码的结果为:

  1. false
  2. true
  3. false
  4. true
  5. false

getCanonicalName() : String

获取元素的规范化名字,该名字定义在Java Language Specification。

  1. public String getCanonicalName() {
  2. if (isArray()) {
  3. String canonicalName = getComponentType().getCanonicalName();
  4. if (canonicalName != null)
  5. return canonicalName + "[]";
  6. else
  7. return null;
  8. }
  9. if (isLocalOrAnonymousClass())
  10. return null;
  11. Class<?> enclosingClass = getEnclosingClass();
  12. if (enclosingClass == null) { // top level class
  13. return getName();
  14. } else {
  15. String enclosingName = enclosingClass.getCanonicalName();
  16. if (enclosingName == null)
  17. return null;
  18. return enclosingName + "." + getSimpleName();
  19. }
  20. }

由源码可知:

  1. 若元素为数组,如果数组存储的数据类型对应的CanonicalName不为null,则返回数组元素类型的CanonicalName +”[]”,否则返回null;
  2. 若元素为本地类或匿名类,返回null;
  3. 若元素为top level类,调用getName()并返回;
  4. 若元素为内部类
    1. 若top level类的CanonicalName不为null,返回top level类的全类名 + “.” + getSimpleName;
    2. 若top level类的CanonicalName为null,返回null ```java LocalClass localClass = new LocalClass(); System.out.println(localClass.localInConstructor.getClass().getCanonicalName()); // 本地类 System.out.println(localClass.localAnonymousInConstructor.getClass().getCanonicalName()); // 匿名类 System.out.println(LocalClass.class.getCanonicalName()); // 顶级类,与getName()相同 System.out.println(LocalClass.class.getName()); // 顶级类 System.out.println(LocalClass.LocalInner.class.getCanonicalName()); // 内部类

LocalClass[] localClasses = new LocalClass[1]; System.out.println(localClasses.getClass().getCanonicalName()); // 数组返回数组元素的CanonicalName

Object instance = Array.newInstance(localClass.localInConstructor.getClass(), 1); System.out.println(instance.getClass().getCanonicalName()); // 数组元素的CanonicalName为null, 返回null

  1. > null
  2. > null
  3. > com.bujian.reflects.model.LocalClass
  4. > com.bujian.reflects.model.LocalClass
  5. > com.bujian.reflects.model.LocalClass.LocalInner
  6. > com.bujian.reflects.model.LocalClass[]
  7. > null
  8. <a name="cy1da"></a>
  9. #### [getName](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getName--)() : String
  10. 返回元素的二进制Name,即全类限定名。
  11. 对于数组而言,getName()返回值格式为**一个或多个"[" **+** 元素类型编码** + **元素的getName()**<br />元素类型和编码:
  12. | 元素类型 | 编码 |
  13. | :---: | :---: |
  14. | boolean | Z |
  15. | byte | B |
  16. | char | C |
  17. | 类或者接口 | L |
  18. | double | D |
  19. | float | F |
  20. | int | I |
  21. | long | J |
  22. | short | S |
  23. | 一维数组 | "[" +数组元素getName |
  24. | n维数组 | n"[" + 数组元素getName |
  25. 对于**本地类**而言,getName()的结果格式为:
  26. ```java
  27. 顶级类getName() + $N(N为出现在源码中的顺序,第一个内部类为$1,第n个为$n) + 本地类getSimpleName()

对于匿名类而言,getName()的结果格式为:

  1. 顶级类getName() + $N(N为出现在源码中的顺序,第一个内部类为$1,第二个为$2,以此类推)

对于内部类而言,getName()的结果格式为:

  1. 顶级类getName() + $ + 内部类getSimpleName()

测试代码:

  1. LocalClass localClass = new LocalClass();
  2. localClass.testLocalInMethod();
  3. System.out.println(LocalClass.class.getName()); // 顶级类
  4. System.out.println(LocalClass.LocalInner.class.getName()); // 内部类
  5. System.out.println(localClass.localInConstructor.getClass().getName()); // 本地类
  6. System.out.println(localClass.localAnonymousInConstructor.getClass().getName()); // 匿名类
  7. System.out.println(localClass.localAnonymousInMethod.getClass().getName()); // 匿名类
  8. LocalClass[] localClasses = new LocalClass[1];
  9. System.out.println(localClasses.getClass().getName()); // 数组返回数组元素的CanonicalName
  10. Object instance = Array.newInstance(localClass.localInConstructor.getClass(), 1);
  11. System.out.println(instance.getClass().getName()); // 数组元素的CanonicalName为null, 返回null
  12. System.out.println(void.class.getName());
  13. System.out.println(boolean.class.getName());
  14. System.out.println(char.class.getName());
  15. System.out.println(byte.class.getName());
  16. System.out.println(int.class.getName());
  17. System.out.println(short.class.getName());
  18. System.out.println(long.class.getName());
  19. System.out.println(float.class.getName());
  20. System.out.println(double.class.getName());
  21. System.out.println(new double[1].getClass().getName());
  22. System.out.println(new long[1].getClass().getName());

com.bujian.reflects.model.LocalClass com.bujian.reflects.model.LocalClass$LocalInner com.bujian.reflects.model.LocalClass$1LocalInConstructor com.bujian.reflects.model.LocalClass$2 com.bujian.reflects.model.LocalClass$3 [Lcom.bujian.reflects.model.LocalClass; [Lcom.bujian.reflects.model.LocalClass$1LocalInConstructor; void boolean char byte int short long float double [D [J

getSimpleName() : String

返回类名字。

  1. 非匿名类返回类名称
  2. 匿名类返回null
  3. 数组返回元素类名称 + “[]”
    1. System.out.println(LocalClass.class.getSimpleName()); // 顶级类
    2. System.out.println(LocalClass.LocalInner.class.getSimpleName()); // 内部类
    3. System.out.println(localClass.localAnonymousInConstructor.getClass().getSimpleName()); // 匿名类
    4. LocalClass[] localClasses = new LocalClass[1];
    5. System.out.println(localClasses.getClass().getSimpleName()); // 数组返回数组元素的CanonicalName

    LocalClass LocalInner null LocalClass[]

  • getTypeName() : String
    1. public String getTypeName() {
    2. if (isArray()) {
    3. try {
    4. Class<?> cl = this;
    5. int dimensions = 0;
    6. while (cl.isArray()) {
    7. dimensions++;
    8. cl = cl.getComponentType();
    9. }
    10. StringBuilder sb = new StringBuilder();
    11. sb.append(cl.getName());
    12. for (int i = 0; i < dimensions; i++) {
    13. sb.append("[]");
    14. }
    15. return sb.toString();
    16. } catch (Throwable e) { /*FALLTHRU*/ }
    17. }
    18. return getName();
    19. }
    由源码可知,除了数组类型,返回值基本与getName()一致,数组返回格式为:数组元素getName + “[]”

    getModifiers() :int

    返回限制符。
    1. public static final int PUBLIC = 0x00000001;
    2. public static final int PRIVATE = 0x00000002;
    3. public static final int PROTECTED = 0x00000004;
    4. public static final int STATIC = 0x00000008;
    5. public static final int FINAL = 0x00000010;
    6. public static final int SYNCHRONIZED = 0x00000020;
    7. public static final int VOLATILE = 0x00000040;
    8. public static final int TRANSIENT = 0x00000080;
    9. public static final int NATIVE = 0x00000100;
    10. public static final int INTERFACE = 0x00000200;
    11. public static final int ABSTRACT = 0x00000400;
    12. public static final int STRICT = 0x00000800;
    13. static final int BRIDGE = 0x00000040;
    14. static final int VARARGS = 0x00000080;
    15. public static final int SYNTHETIC = 0x00001000;
    16. static final int ANNOTATION = 0x00002000;
    17. static final int ENUM = 0x00004000;
    18. static final int MANDATED = 0x00008000;

    isArray() : boolean

    isEnum(): boolean

    isInterface() : boolean

    isMemberClass(): boolean true表示非静态内部类

    isPrimitive() : boolean

    isSynthetic(): boolean

    getGenericInterfaces() : Type[] 返回直接实现的接口Type

    getGenericSuperclass() :返回直接父类的Type

    反射创建数组

java.lang.reflect.Array

static newInstance(Class<?> componentType, int length) : Object

componentType 表示元素类型, length表示其长度。

  1. Object array = Array.newInstance(String.class, 4);
  2. // 设置数据
  3. Array.set(array, 0, "第一个元素");
  4. Array.set(array, 2, "第3个元素");
  5. System.out.println(Arrays.toString((String[]) array));

[第一个元素, null, 第3个元素, null]

Array常用方法

  • static get(Object array, int index) :Object 获取Object类型元素
  • static set(Object array, int index, Object value) :void 设置Object类型元素
  • static getBoolean(Object array, int index) :boolean
  • static setBoolean(Object array, int index, boolean z) :void
  • static getByte(Object array, int index) :byte
  • static setByte(Object array, int index, bytez) :void
  • static getChar(Object array, int index) :Char
  • static setChar(Object array, int index, Char z) :void
  • static getShort(Object array, int index) :short
  • static setShort(Object array, int index, shortz) :void
  • static getInt(Object array, int index) :int
  • static setInt(Object array, int index, intz) :void
  • static getLong(Object array, int index) :long
  • static setLong(Object array, int index, longz) :void
  • static getFloat(Object array, int index) :floar
  • static setFloat(Object array, int index, float z) :void
  • static getDouble(Object array, int index) :double
  • static setDouble(Object array, int index, double z) :void