- 为什么需要反射
- 反射主要功能
- 反射缺点
- 反射基本应用
- 测试代码
- 获取Class对象
- 判断是否为某个类实例
- 创建实例
- 获取方法
- Method">getMethod(String name, Class<?>… parameterTypes) : Method
- getMethods() : Method[]
- getDeclaredMethod(String name, Class<?>… parameterTypes) :Method">getDeclaredMethod(String name, Class<?>… parameterTypes) :Method
- getDeclaredMethods() : Method[]">getDeclaredMethods() : Method[]
- getEnclosingMethod() :Method">getEnclosingMethod() :Method
- 获取Filed
- getField(String name) : Field">getField(String name) : Field
- getFields() : Field[]">getFields() : Field[]
- getDeclaredField(String name) : Field">getDeclaredField(String name) : Field
- getDeclaredFields() : Field[]">getDeclaredFields() : Field[]
- 获取注解信息(只能获取到运行时注解)
- getAnnotation(Class annotationClass) : A"> getAnnotation(Class annotationClass) : A
- getAnnotations() :Annotation[]">getAnnotations() :Annotation[]
- getDeclaredAnnotation(Class annotationClass) : A"> getDeclaredAnnotation(Class annotationClass) : A
- getDeclaredAnnotations() :Annotation[]">getDeclaredAnnotations() :Annotation[]
- isAnnotation() : boolean">isAnnotation() : boolean
- isAnnotationPresent(Class<? extends Annotation> annotationClass) : boolean">isAnnotationPresent(Class<? extends Annotation> annotationClass) : boolean
- getAnnotationsByType(Class annotationClass) :A[]"> getAnnotationsByType(Class annotationClass) :A[]
- getDeclaredAnnotationsByType(Class annotationClass) :A[]"> getDeclaredAnnotationsByType(Class annotationClass) :A[]
- 反射注解使用实例
- getAnnotationsByType使用示例">getAnnotationsByType使用示例
- Class常用方法
- isLocalClass() : boolean">isLocalClass() : boolean
- isAnonymousClass() : boolean">isAnonymousClass() : boolean
- getCanonicalName() : String">getCanonicalName() : String
- getSimpleName() : String">getSimpleName() : String
- getModifiers() :int">getModifiers() :int
- isArray() : boolean">isArray() : boolean
- isEnum(): boolean">isEnum(): boolean
- isInterface() : boolean">isInterface() : boolean
- isMemberClass(): boolean true表示非静态内部类">isMemberClass(): boolean true表示非静态内部类
- isPrimitive() : boolean">isPrimitive() : boolean
- isSynthetic(): boolean">isSynthetic(): boolean
- getGenericInterfaces() : Type[] 返回直接实现的接口Type">getGenericInterfaces() : Type[] 返回直接实现的接口Type
- getGenericSuperclass() :返回直接父类的Type">getGenericSuperclass() :返回直接父类的Type
- 反射创建数组
- newInstance(Class<?> componentType, int length) : Object">static newInstance(Class<?> componentType, int length) : Object
- Array常用方法
反射是Java的特征之一,允许在程序运行时获取自身的信息,并且可以操作类或对象的内部属性。
为什么需要反射
- 提高程序的灵活度
- 在平常开发者,由于有访问修饰符(public,default,protected,private)的限制,很多时候我们不能访问或者修改某些类的某些实现,这个时候反射就可以帮着我们达到这个目的。比如,通过ScrollView的mScroller字段获取对应的OverScroller对象,用来判断ScrollView的滚动状态;
- 根据不同的配置加载不同的类或对象
- 屏蔽实现的细节,让使用者更加方便
- 组件化中,下层组件提供接口Inter,上层组件B提供具体实现屏蔽,对外提供实现类全类名,上层组件C就可以根据该全类名通过反射生成对应的Inter实例并转化为Inter类型,来调用接口方法。这样组件C不用知道B中的具体实现,直接使用即可。
反射主要功能
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
- 在运行时调用任意一个对象的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 在运行时获取泛型信息;
- 在运行时处理注解;
- 生成动态代理;
反射缺点
- 反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象
- 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题
反射基本应用
测试代码
Parent.java
package com.bujian.reflects.model;public class Parent {String defaultParentFiled;public String publicParentFiled;private String privateParentFiled;protected String protectedParentFiled;public Parent() {}public Parent(String defaultParentFiled) {this.defaultParentFiled = defaultParentFiled;}Parent(String defaultParentFiled, String protectedParentFiled) {this.defaultParentFiled = defaultParentFiled;this.protectedParentFiled = protectedParentFiled;}protected Parent(String defaultParentFiled, String protectedParentFiled, String privateParentFiled) {this.defaultParentFiled = defaultParentFiled;this.protectedParentFiled = protectedParentFiled;this.privateParentFiled = privateParentFiled;}private Parent(String defaultParentFiled, String protectedParentFiled, String privateParentFiled, String publicParentFiled) {this.defaultParentFiled = defaultParentFiled;this.protectedParentFiled = protectedParentFiled;this.privateParentFiled = privateParentFiled;this.publicParentFiled = publicParentFiled;}@Overridepublic String toString() {return "Parent{" +"defaultParentFiled='" + defaultParentFiled + '\'' +'}';}public void publicParentMethod() {System.out.println("publicParentMethod");}void defaultParentMethod() {System.out.println("defaultParentMethod");}protected void protectedParentMethod() {System.out.println("protectedParentMethod");}private void privateParentMethod() {System.out.println("privateParentMethod");}}
Child.java
package com.bujian.reflects.model;/*** 父类*/public class Child extends Parent {String defaultChildFiled;public String publicChildFiled;private String privateChildFiled;protected String protectedChildFiled;public Child() {}public Child(String defaultChildFiled) {this.defaultChildFiled = defaultChildFiled;}Child(String defaultChildFiled, String protectedChildFiled) {this.defaultChildFiled = defaultChildFiled;this.protectedChildFiled = protectedChildFiled;}protected Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled) {this.defaultChildFiled = defaultChildFiled;this.protectedChildFiled = protectedChildFiled;this.privateChildFiled = privateChildFiled;}private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled) {this.defaultChildFiled = defaultChildFiled;this.protectedChildFiled = protectedChildFiled;this.privateChildFiled = privateChildFiled;this.publicChildFiled = publicChildFiled;}public void publicChildMethod() {System.out.println("publicChildMethod");}public void defaultChildMethod() {System.out.println("defaultChildMethod");}protected void protectedChildMethod() {System.out.println("protectedChildMethod");}private void privateChildMethod() {System.out.println("privateChildMethod");}@Overridepublic String toString() {return "Child{" +"defaultChildFiled='" + defaultChildFiled + '\'' +'}';}// 非静态内部类public class InnerChild {public InnerChild() {}}}
获取Class对象
反射通过获取Class对象进而获取相关类的所有信息。Class获取的方式有3种:
使用Class.forName方法。例如,获取String的Class对象:
Class<?> stringClass = Class.forName("java.lang.String");
通过类型获取
Class<?> intClass = int.class;Class<?> integerClass = Integer.class;
通过对象的getClass方法获取
Class<?> stringClass = "".getClass();
判断是否为某个类实例
isAssignableFrom(Class<?> cls):该类是否是参数cls自身或超集
public boolean isAssignableFrom(Class<?> cls) {if (this == cls) {return true; // Can always assign to things of the same type.} else if (this == Object.class) {// Object不是基本类型的父类或父接口return !cls.isPrimitive();} else if (isArray()) {// componentType表示的是数组元素的具体类型return cls.isArray() && componentType.isAssignableFrom(cls.componentType);} else if (isInterface()) {// 参数是否实现了该接口Object[] iftable = cls.ifTable;if (iftable != null) {for (int i = 0; i < iftable.length; i += 2) {if (iftable[i] == this) {return true;}}}return false;} else {if (!cls.isInterface()) {for (cls = cls.superClass; cls != null; cls = cls.superClass) {if (cls == this) {return true;}}}return false;}}
实例:
Class<?> stringClass = Class.forName("java.lang.String");boolean assignableFrom = stringClass.isAssignableFrom(Object.class); // falseboolean assignable = Object.class.isAssignableFrom(stringClass); // trueboolean intAssignable = Object.class.isAssignableFrom(int.class); // false
isInstance(Object obj):是否是obj的超集,内部实现是isAssignableFrom(Class<?> cls)
public boolean isInstance(Object obj) {if (obj == null) {return false;}return isAssignableFrom(obj.getClass());}
示例:
boolean isInstance1 = stringClass.isInstance(new Object()); // falseboolean isInstance2 = Object.class.isInstance(""); // trueboolean isInstance3 = Object.class.isInstance((int)2); // true,注意,这里将int自动装箱成为了Integer
getComponentType():获取数组元素类型
int[] ints = new int[2];Class<? extends int[]> intsClass = ints.getClass();Class<?> componentType = intsClass.getComponentType(); // intClass<?> componentType1 = new String[2].getClass().getComponentType(); // class java.lang.String
创建实例
getConstructor(Class<?>… parameterTypes) : Constructor
获取访问修饰符为public的构造方法。如果有多个public构造器,通过方法参数类型(parameterTypes)来区分想要调用哪一个。
注意:如果class表示的是一个非静态内部类,那么外层类将作为第一个参数传入
Class<? extends Child> childClass = Child.class;Constructor<? extends Child> childClassConstructor = childClass.getConstructor();Child child = childClassConstructor.newInstance();// 方法参数类型需要一一对应,否则会报IllegalArgumentException异常// java.lang.IllegalArgumentException: Wrong number of arguments; expected 0, got 1// child = childClassConstructor.newInstance("defaultString");System.out.println(child); // Child{defaultChildFiled='null'}childClassConstructor = childClass.getConstructor(String.class);child = childClassConstructor.newInstance("defaultString");System.out.println(child); // Child{defaultChildFiled='defaultString'}// 对于非静态内部类,外部类作为第一个参数传入Class<Child.InnerChild> innerChildClass = Child.InnerChild.class;// 报异常:java.lang.NoSuchMethodException: <init> []// Constructor<Child.InnerChild> innerChildConstructor = innerChildClass.getConstructor();// 正确写法:Child.class作为第一个参数Constructor<Child.InnerChild> innerChildConstructor = innerChildClass.getConstructor(Child.class);System.out.println(innerChildConstructor.getName());
getConstructors() : Constructor<?>[]
返回所有声明为public的构造器。返回值是一个数组,假设数组长度为0,表示这个类不存在
返回值数组长度为0的情况:
- 该类不存在public的构造器
- 该类是基本类型、数组类型或void
打印结果:Constructor<?>[] constructors = childClass.getConstructors();Arrays.stream(constructors).filter(Objects::nonNull).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异常
**
// private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled)Constructor<? extends Child> constructor = childClass.getDeclaredConstructor(String.class, String.class, String.class, String.class);System.out.println(constructor.toString());//Child declareChild = constructor.newInstance("defaultChildFiled", "protectedChildFiled", "privateChildFiled", "publicChildFiled");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
// private Child(String defaultChildFiled, String protectedChildFiled, String privateChildFiled, String publicChildFiled)Constructor<? extends Child> constructor = childClass.getDeclaredConstructor(String.class, String.class, String.class, String.class);System.out.println(constructor.toString());constructor.setAccessible(true);Child declareChild = constructor.newInstance("defaultChildFiled", "protectedChildFiled", "privateChildFiled", "publicChildFiled");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对应类的所有构造方法
Constructor<?>[] declaredConstructors = childClass.getDeclaredConstructors();Arrays.stream(declaredConstructors).filter(Objects::nonNull).forEach(c -> {c.setAccessible(true);System.out.println(c.toString());});
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实例。例如:
package com.bujian.reflects.model;public class OuterCloser {public Object mEncloser;public OuterCloser() {class Encloser {}mEncloser = new Encloser();}}// 测试OuterCloser outerCloser = new OuterCloser();Class<?> aClass = outerCloser.mEncloser.getClass();Constructor<?> enclosingConstructor = aClass.getEnclosingConstructor();System.out.println(enclosingConstructor);
public com.bujian.reflects.model.OuterCloser()
获取方法
getMethod(String name, Class<?>… parameterTypes) : Method
获取public修饰符限制的方法。name表示方法名,parameterTypes表示方法参数。
注意:
- 如果没有参数,什么都不用填;
- 如果在本类找不到对应的方法,会向上其父类和接口递归查找;
- 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
getAnnotations() :Annotation[]
getDeclaredAnnotation(Class annotationClass) : A
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 在运行期有效,不具备继承性
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface RuntimeAnno {}
com.bujian.reflects.anno.RuntimeInheritAnno 在运行期有效,具备继承性
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Inherited // 具备继承性。例如,AnnotationModel有该注解标注,那么其子类AnnotationChildModel也可以使用该注解public @interface RuntimeInheritAnno {}
com.bujian.reflects.anno.ClassAnno 仅在编译期有效,不具备继承性
@Retention(RetentionPolicy.CLASS)@Target(ElementType.TYPE)public @interface ClassAnno {}
com.bujian.reflects.anno.ClassInheritAnno 仅在编译期有效,具备继承性
@Retention(RetentionPolicy.CLASS)@Target(ElementType.TYPE)public @interface ClassInheritAnno {}
com.bujian.reflects.model.AnnotationModel
@RuntimeAnno@RuntimeInheritAnno@ClassAnno@ClassInheritAnnopublic class AnnotationModel {}
com.bujian.reflects.model.AnnotationChildModel
public class AnnotationChildModel {}
System.out.println(AnnotationModel.class.getAnnotation(ClassAnno.class));System.out.println(AnnotationChildModel.class.getAnnotation(ClassAnno.class));System.out.println(AnnotationModel.class.getDeclaredAnnotation(ClassAnno.class));System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(ClassAnno.class));System.out.println(AnnotationModel.class.getAnnotation(ClassInheritAnno.class));System.out.println(AnnotationChildModel.class.getAnnotation(ClassInheritAnno.class));System.out.println(AnnotationModel.class.getDeclaredAnnotation(ClassInheritAnno.class));System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(ClassInheritAnno.class));System.out.println(AnnotationModel.class.getAnnotation(RuntimeAnno.class));System.out.println(AnnotationChildModel.class.getAnnotation(RuntimeAnno.class));System.out.println(AnnotationModel.class.getDeclaredAnnotation(RuntimeAnno.class));System.out.println(AnnotationChildModel.class.getDeclaredAnnotation(RuntimeAnno.class));System.out.println(AnnotationModel.class.getAnnotation(RuntimeInheritAnno.class));System.out.println(AnnotationChildModel.class.getAnnotation(RuntimeInheritAnno.class));System.out.println(AnnotationModel.class.getDeclaredAnnotation(RuntimeInheritAnno.class));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使用示例
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface RepeatableModels {RepeatableModel[] value();}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)// 当我们需要重复使用某个注解来达到相同注解表现出不同的形式时,可以使用Repeatable注解// Repeatable括号内的注解相当于用来该注解(RepeatableModel)的内容容器@Repeatable(RepeatableModels.class)public @interface RepeatableModel {String repeatableString() default "repeat";}@RepeatableModel(repeatableString = "bujian")@RepeatableModel(repeatableString = "oliver")@RepeatableModel(repeatableString = "coco")public class RepeatContent {}// 使用Annotation[] annotations = RepeatContent.class.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}RepeatableModel[] models = RepeatContent.class.getAnnotationsByType(RepeatableModel.class);for (RepeatableModel model : models) {System.out.println(model);System.out.println(model.repeatableString());}
@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获取的话,也可以通过遍历数组获取:
Annotation[] annotations = RepeatContent.class.getAnnotations();RepeatableModels repeatableModels = (RepeatableModels) annotations[0];for (Annotation annotation : repeatableModels.value()) {System.out.println(annotation);}
@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表示这是一个本地类。源码如下:
public boolean isLocalClass() {return (getEnclosingMethod() != null || getEnclosingConstructor() != null)&& !isAnonymousClass();}
通过源码可以知道,本地类就是一个定义在方法中或构造方法中的非匿名类。
package com.bujian.reflects.model;public class LocalClass {public Object localInMethod;public Object localAnonymousInMethod;public Object localInConstructor;public Object localAnonymousInConstructor;public Object localAnonymous = new Predicate<String>() {@Overridepublic boolean test(String s) {return false;}};public LocalClass() {class LocalInConstructor {}this.localInConstructor = new LocalInConstructor();this.localAnonymousInConstructor = new Predicate<String>() {@Overridepublic boolean test(String s) {return false;}};}public void testLocalInMethod() {class LocalInMethod {}this.localInMethod = new LocalInMethod();this.localAnonymousInMethod = new Predicate<String>() {@Overridepublic boolean test(String s) {return false;}};}public class LocalInner {}}
测试代码:
LocalClass localClass = new LocalClass();localClass.testLocalInMethod();System.out.println(localClass.localInConstructor.getClass().isLocalClass());System.out.println(localClass.localAnonymousInConstructor.getClass().isLocalClass());System.out.println(localClass.localInMethod.getClass().isLocalClass());System.out.println(localClass.localAnonymousInMethod.getClass().isLocalClass());System.out.println(LocalClass.LocalInner.class.isLocalClass());
true false true false false
isAnonymousClass() : boolean
返回true表示这是一个匿名类。该方法是一个本地方法。
@FastNativepublic native boolean isAnonymousClass();
上述测试代码的结果为:
falsetruefalsetruefalse
getCanonicalName() : String
获取元素的规范化名字,该名字定义在Java Language Specification。
public String getCanonicalName() {if (isArray()) {String canonicalName = getComponentType().getCanonicalName();if (canonicalName != null)return canonicalName + "[]";elsereturn null;}if (isLocalOrAnonymousClass())return null;Class<?> enclosingClass = getEnclosingClass();if (enclosingClass == null) { // top level classreturn getName();} else {String enclosingName = enclosingClass.getCanonicalName();if (enclosingName == null)return null;return enclosingName + "." + getSimpleName();}}
由源码可知:
- 若元素为数组,如果数组存储的数据类型对应的CanonicalName不为null,则返回数组元素类型的CanonicalName +”[]”,否则返回null;
- 若元素为本地类或匿名类,返回null;
- 若元素为top level类,调用getName()并返回;
- 若元素为内部类
- 若top level类的CanonicalName不为null,返回top level类的全类名 + “.” + getSimpleName;
- 若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
> null> null> com.bujian.reflects.model.LocalClass> com.bujian.reflects.model.LocalClass> com.bujian.reflects.model.LocalClass.LocalInner> com.bujian.reflects.model.LocalClass[]> null<a name="cy1da"></a>#### [getName](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getName--)() : String返回元素的二进制Name,即全类限定名。对于数组而言,getName()返回值格式为**一个或多个"[" **+** 元素类型编码** + **元素的getName()**<br />元素类型和编码:| 元素类型 | 编码 || :---: | :---: || boolean | Z || byte | B || char | C || 类或者接口 | L || double | D || float | F || int | I || long | J || short | S || 一维数组 | "[" +数组元素getName || n维数组 | n个"[" + 数组元素getName |对于**本地类**而言,getName()的结果格式为:```java顶级类getName() + $N(N为出现在源码中的顺序,第一个内部类为$1,第n个为$n) + 本地类getSimpleName()
对于匿名类而言,getName()的结果格式为:
顶级类getName() + $N(N为出现在源码中的顺序,第一个内部类为$1,第二个为$2,以此类推)
对于内部类而言,getName()的结果格式为:
顶级类getName() + $ + 内部类getSimpleName()
测试代码:
LocalClass localClass = new LocalClass();localClass.testLocalInMethod();System.out.println(LocalClass.class.getName()); // 顶级类System.out.println(LocalClass.LocalInner.class.getName()); // 内部类System.out.println(localClass.localInConstructor.getClass().getName()); // 本地类System.out.println(localClass.localAnonymousInConstructor.getClass().getName()); // 匿名类System.out.println(localClass.localAnonymousInMethod.getClass().getName()); // 匿名类LocalClass[] localClasses = new LocalClass[1];System.out.println(localClasses.getClass().getName()); // 数组返回数组元素的CanonicalNameObject instance = Array.newInstance(localClass.localInConstructor.getClass(), 1);System.out.println(instance.getClass().getName()); // 数组元素的CanonicalName为null, 返回nullSystem.out.println(void.class.getName());System.out.println(boolean.class.getName());System.out.println(char.class.getName());System.out.println(byte.class.getName());System.out.println(int.class.getName());System.out.println(short.class.getName());System.out.println(long.class.getName());System.out.println(float.class.getName());System.out.println(double.class.getName());System.out.println(new double[1].getClass().getName());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
返回类名字。
- 非匿名类返回类名称
- 匿名类返回null
- 数组返回元素类名称 + “[]”
System.out.println(LocalClass.class.getSimpleName()); // 顶级类System.out.println(LocalClass.LocalInner.class.getSimpleName()); // 内部类System.out.println(localClass.localAnonymousInConstructor.getClass().getSimpleName()); // 匿名类LocalClass[] localClasses = new LocalClass[1];System.out.println(localClasses.getClass().getSimpleName()); // 数组返回数组元素的CanonicalName
LocalClass LocalInner null LocalClass[]
- getTypeName() : String
由源码可知,除了数组类型,返回值基本与getName()一致,数组返回格式为:数组元素getName + “[]”。public String getTypeName() {if (isArray()) {try {Class<?> cl = this;int dimensions = 0;while (cl.isArray()) {dimensions++;cl = cl.getComponentType();}StringBuilder sb = new StringBuilder();sb.append(cl.getName());for (int i = 0; i < dimensions; i++) {sb.append("[]");}return sb.toString();} catch (Throwable e) { /*FALLTHRU*/ }}return getName();}
getModifiers() :int
返回限制符。public static final int PUBLIC = 0x00000001;public static final int PRIVATE = 0x00000002;public static final int PROTECTED = 0x00000004;public static final int STATIC = 0x00000008;public static final int FINAL = 0x00000010;public static final int SYNCHRONIZED = 0x00000020;public static final int VOLATILE = 0x00000040;public static final int TRANSIENT = 0x00000080;public static final int NATIVE = 0x00000100;public static final int INTERFACE = 0x00000200;public static final int ABSTRACT = 0x00000400;public static final int STRICT = 0x00000800;static final int BRIDGE = 0x00000040;static final int VARARGS = 0x00000080;public static final int SYNTHETIC = 0x00001000;static final int ANNOTATION = 0x00002000;static final int ENUM = 0x00004000;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表示其长度。
Object array = Array.newInstance(String.class, 4);// 设置数据Array.set(array, 0, "第一个元素");Array.set(array, 2, "第3个元素");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
