Facebook Twitter LinkedIn E-mail
magnify
Home Posts tagged "反射"

Java Reflection 教程(8):Annotations类标注

前面Java 标注(Annotations)介绍 介绍了Java代码中Annotation的用法,使用Java Reflection API 也可以用来方法类,类成员或类方法的Annotation定义。

1.类Annotations

可以通过Class 的getAnnotations 来方法类的标注定义:

Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();

for(Annotation annotation : annotations){
 if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
 }
}

或者通过指定Annotation类型来访问类的标注:

Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
}

2. 类方法Annotations

类似的方法可以访问类方法的标注,如下例:

public class TheClass {
 @MyAnnotation(name="someName",  value = "Hello World")
 public void doSomething(){}
}

...
Method method = ... //obtain method object
Annotation[] annotations = method.getDeclaredAnnotations();

for(Annotation annotation : annotations){
 if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
 }
}

或者指定Annotation类型:

Method method = ... // obtain method object
Annotation annotation = method.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
}

3. 参数Annotations

访问参数的标注,如下例:

public class TheClass {
 public static void doSomethingElse(
 @MyAnnotation(name="aName", value="aValue") String parameter){
 }
}
...
Method method = ... //obtain method object
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes();

int i=0;
for(Annotation[] annotations : parameterAnnotations){
 Class parameterType = parameterTypes[i++];

 for(Annotation annotation : annotations){
 if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("param: " + parameterType.getName());
 System.out.println("name : " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
 }
 }
}

4.  类成员Annotation

访问类成员标注的例子如下:

public class TheClass {

 @MyAnnotation(name="someName",  value = "Hello World")
 public String myField = null;
}
...

Field field = ... //obtain field object
Annotation[] annotations = field.getDeclaredAnnotations();

for(Annotation annotation : annotations){
 if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
 }
}

或者

Field field = ... // obtain method object
Annotation annotation = field.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
 MyAnnotation myAnnotation = (MyAnnotation) annotation;
 System.out.println("name: " + myAnnotation.name());
 System.out.println("value: " + myAnnotation.value());
}
 

Java Reflection 教程(7):类私有成员变量和方法

一般来说,不可以访问类的私有成员变量和调用类的私有方法。但通过Java Reflection API可以绕过这个限制,前面使用的getMethods, getFields,getConstructors 等方法都是返回的类的public 方法,类成员和构造函数。

本篇介绍如何使用Java Reflection API来访问类的私有成员。

1. 访问私有成员

Class的getDeclaredField(String name) 和getDeclaredFields 可以返回类的所有成员变量包括私有成员变量。

public class PrivateObject {

 private String privateString = null;

 public PrivateObject(String privateString) {
 this.privateString = privateString;
 }
}

....

PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
 getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

上面代码可以方法类PrivateObject的私有成员privateString。要注意的是privateStringField.setAccessible(true); 必须打开类成员的访问控制后才可以访问该私有成员。也只有使用Java Reflection API 才可以访问类的私有成员。

2. 访问类的私有方法

同样Class的getDeclaredMethod(String name) 和getDeclaredMethods 可以用来访问类额私有方法。

public class PrivateObject {

 private String privateString = null;

 public PrivateObject(String privateString) {
 this.privateString = privateString;
 }

 private String getPrivateString(){
 return this.privateString;
 }
}

...
PrivateObject privateObject = new PrivateObject("The Private Value");

Method privateStringMethod = PrivateObject.class.
 getDeclaredMethod("getPrivateString", null);

privateStringMethod.setAccessible(true);

String returnValue = (String)
 privateStringMethod.invoke(privateObject, null);

System.out.println("returnValue = " + returnValue);


同样需要调用privateStringMethod.setAccessible(true); 打开对该私有方法的访问控制后才可访问该私有成员方法。

 

Java Reflection 教程(6):Getters和Setters

Java 的类常常带有setter 和getter 为类的成员变量赋值(类的属性)。setter 一般指以set开始的成员方法用于设置类的某个属性值,而getter 一般指一get开始的成员方法,用于去的类的某个属性值。setter 一般只带一个参数,而getter不带参数。

下面的代码可以用来判断getter 和setter 方法:

public static void printGettersSetters(Class aClass){
 Method[] methods = aClass.getMethods();

 for(Method method : methods){
 if(isGetter(method)) System.out.println("getter: " + method);
 if(isSetter(method)) System.out.println("setter: " + method);
 }
}

public static boolean isGetter(Method method){
 if(!method.getName().startsWith("get"))      return false;
 if(method.getParameterTypes().length != 0)   return false;
 if(void.class.equals(method.getReturnType()) return false;
 return true;
}

public static boolean isSetter(Method method){
 if(!method.getName().startsWith("set")) return false;
 if(method.getParameterTypes().length != 1) return false;
 return true;
}

 

Java Reflection 教程(5):Methods 类方法

通过Class 的getMethods 可以取的类方法的定义

Class aClass = ...//obtain class object
Method[] methods = aClass.getMethods();

如果知道类方法的参数类型,则可以使用getMethod 取的对应的方法定义,如:

Class  aClass = ...//obtain class object
Method method =
 aClass.getMethod("doSomething", new Class[]{String.class});

上例取的方法名为doSomething 带一个String为参数的方法定义。如果找不到对应的方法,Java Reflection 抛出NoSuchMethodException 异常。

如果需要方法的方法不带参数,则使用null 做为getMethod的第二个参数,如下:

Class  aClass = ...//obtain class object
Method method =
 aClass.getMethod("doSomething", null);

1. 获取方法的参数和返回值定义

获取参数定义

Method method = ... // obtain method - see above
Class[] parameterTypes = method.getParameterTypes();

获取返回值定义

Method method = ... // obtain method - see above
Class returnType = method.getReturnType();

2. 使用Method对象调用该方法

//get method that takes a String as argument
Method method = MyObject.class.getMethod("doSomething", String.class);

Object returnValue = method.invoke(null, "parameter-value1");

method.invoke 的调用个参数为该方法对应的类对象,如果方法为static 类型,则使用null,后面的参数为该方法的参数值。

 

Java Reflection 教程(4):Fields 成员变量

类的成员变量定义可以通过Class 的getFields()来取得

Class aClass = ...//obtain class object
Field[] methods = aClass.getFields();

如果知道Field的名称,则可以通过getField() 取得对应的Field定义

Class  aClass = MyObject.class
Field field = aClass.getField("someField");

对应到类的定义可以如下:

public class MyObject{
 public String someField = null;

}

如果找不到对应的Field定义,Java Reflection API 抛出NoSuchFieldException异常。

1. 获取成员变量名称

Field field = ... //obtain field object
String fieldName = field.getName();

2. 获取成员变量类型

Field field = aClass.getField("someField");
Object fieldType = field.getType();

3. 为成员变量赋值或取得成员变量的值

Class  aClass = MyObject.class
Field field = aClass.getField("someField");

MyObject objectInstance = new MyObject();

Object value = field.get(objectInstance);

field.set(objetInstance, value);

如果Field为Static类型,则使用null 作为get,set 的首参数。

 

Java Reflection 教程(3):Constructor 构造函数

通过Class的getConstructors 可以取得类的所有构造函数定义。

Class aClass = ...//obtain class object
Constructor[] constructors = aClass.getConstructors();

如果知道构造函数的参数定义,可以直接取得对应的构造函数,如:

Class aClass = ...//obtain class object
Constructor constructor =
 aClass.getConstructor(new Class[]{String.class});

如果Reflection API找不到对应的构造函数,则抛出NoSuchMethodException异常。

1. 获取构造函数的参数定义

Class[] parameterTypes = constructor.getParameterTypes();

2. 使用构造函数定义创建实例

//get constructor that takes a String as argument
Constructor constructor = MyObject.class.getConstructor(String.class);

MyObject myObject = (MyObject)
 constructor.newInstance("constructor-arg1");

newInstance 的参数可以选,调用时参数个数必须和对应的Constructor 定义的参数个数一致。