- 为什么需要反射
- 反射主要功能
- 反射缺点
- 反射基本应用
- 测试代码
- 获取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;
}
@Override
public 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");
}
@Override
public 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); // false
boolean assignable = Object.class.isAssignableFrom(stringClass); // true
boolean 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()); // false
boolean isInstance2 = Object.class.isInstance(""); // true
boolean 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(); // int
Class<?> 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
@ClassInheritAnno
public 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>() {
@Override
public boolean test(String s) {
return false;
}
};
public LocalClass() {
class LocalInConstructor {
}
this.localInConstructor = new LocalInConstructor();
this.localAnonymousInConstructor = new Predicate<String>() {
@Override
public boolean test(String s) {
return false;
}
};
}
public void testLocalInMethod() {
class LocalInMethod {
}
this.localInMethod = new LocalInMethod();
this.localAnonymousInMethod = new Predicate<String>() {
@Override
public 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表示这是一个匿名类。该方法是一个本地方法。
@FastNative
public native boolean isAnonymousClass();
上述测试代码的结果为:
false
true
false
true
false
getCanonicalName() : String
获取元素的规范化名字,该名字定义在Java Language Specification。
public String getCanonicalName() {
if (isArray()) {
String canonicalName = getComponentType().getCanonicalName();
if (canonicalName != null)
return canonicalName + "[]";
else
return null;
}
if (isLocalOrAnonymousClass())
return null;
Class<?> enclosingClass = getEnclosingClass();
if (enclosingClass == null) { // top level class
return 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()); // 数组返回数组元素的CanonicalName
Object instance = Array.newInstance(localClass.localInConstructor.getClass(), 1);
System.out.println(instance.getClass().getName()); // 数组元素的CanonicalName为null, 返回null
System.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