Java反射
-
反射是java语言一个非常重要的特点,通过反射,可以在运行时获取类的信息,创建对象,操作对象的属性,执行对象的方法,获取注解等。
-
在日常的开发过程中,反射的使用可能并不多,所以比较的陌生,但了解熟悉后,反射还是比较简单的,只是对一些API的运用。
-
反射主要涉及Class类和java.lang.reflect包中类。
下面通过实际的代码来说明反射的使用:
ReflectionDemo.java
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by hehelt on 16/7/30.
*/
public class ReflectionDemo {
public static void main(String[] args) {
/*------------------获取Class,总共有三种方法--------------------------*/
// Class personClass = getPersonClass(1);
// Class personClass = getPersonClass(2);
// Class personClass = getPersonClass(3);
/*----------------创建对象-----------------*/
// createPerson();
/*------------------操作属性--------------------------*/
// getFields();
// getField("age");
// getFieldValue();
// setFieldValue();
/*----------------操作方法----------------*/
// getMethods();
// doMethod();
// getAnnotation();
}
/**
* 获取Class对象,总共三种方法
*
* @param index 方法的序号
* @return
*/
private static Class getPersonClass(int index) {
Class personClass = null;
switch (index) {
case 1:
// 第一种方法,直接类名后加上.class
personClass = Person.class;
break;
case 2:
// 第二种方法,每一个对象都有getClass()方法
Person person = new Person();
personClass = person.getClass();
break;
case 3:
// 第三种方法,Class的静态方法forName(String className),className为包名+类名
try {
personClass = Class.forName("com.example.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
break;
}
return personClass;
}
/**
* 创建对象
*/
public static void createPerson() {
Class personClass = getPersonClass(1);
try {
// 无惨构造函数
Constructor constructor = personClass.getConstructor(null);
Person person = (Person) constructor.newInstance(null);
System.out.println(person.getName());
// 有参构造函数
Constructor constructor1 = personClass.getConstructor(String.class);
person = (Person) constructor1.newInstance("haha");
System.out.println(person.getName());
// 构造函数为private时
Constructor constructor2 = personClass.getDeclaredConstructor(int.class, String.class);
constructor2.setAccessible(true);
person = (Person) constructor2.newInstance(13, "hello");
System.out.print(person.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 获取所有的属性
*/
public static void getFields() {
Class personClass = getPersonClass(3);
// 权限为public的属性
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
// 所有属性
fields = personClass.getDeclaredFields();
personClass.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
}
/**
* 根据属性名称获取属性
*/
public static void getField() {
Class personClass = getPersonClass(3);
try {
// 属性的权限为public
Field field = personClass.getField("name");
System.out.println(field.getName());
// 属性的权限不为public
Field ageField = personClass.getDeclaredField("age");
System.out.println(ageField.getName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
/**
* 获取对象的属性值
*/
private static void getFieldValue() {
Class personClass = getPersonClass(3);
Person person = new Person();
try {
// 权限不为public的属性
Field field = personClass.getDeclaredField("age");
field.setAccessible(true);// 默认为false,为true时,系统不会验证权限;为false时,系统会检验权限.当需要操作的属性不为public时,需要设置该值为true,避免权限不足导致操作失败.
int age = field.getInt(person);
System.out.println(age);
// 权限为public的属性
Field nameField = personClass.getField("name");
String name = (String) nameField.get(person);
System.out.println(name);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 设置属性的值
*/
public static void setFieldValue() {
Class personClass = getPersonClass(3);
Person person = new Person();
try {
// 属性的权限为public
Field field = personClass.getField("name");
System.out.println(field.get(person));
field.set(person, "hehe");
System.out.println(field.get(person));
// 属性的权限不为public
Field ageField = personClass.getDeclaredField("age");
ageField.setAccessible(true);// 默认为false,为true时,系统不会验证权限;为false时,系统会检验权限.当需要操作的属性不为public时,需要设置该值为true,避免权限不足导致操作失败.
System.out.println(ageField.getInt(person) + "");
ageField.set(person, 10);
System.out.println(ageField.getInt(person) + "");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 获取类的方法
*/
public static void getMethods() {
Class personClass = getPersonClass(3);
// 权限为public的方法,包括父类中的方法
Method[] methods = personClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
System.out.println("--------------");
// 所有属性,不包括父类的方法
methods = personClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
}
/**
* 获取类的方法
*/
public static void getMethod() {
Class personClass = getPersonClass(3);
try {
Method getNameMethod = personClass.getMethod("getName");
System.out.println(getNameMethod.getName());
Method setNameMethod = personClass.getMethod("setName", String.class);
System.out.println(setNameMethod.getName());
Method getAgeMethod = personClass.getDeclaredMethod("getAge");
System.out.println(getAgeMethod.getName());
Method setAgeMethod = personClass.getDeclaredMethod("setAge", int.class);
System.out.println(setAgeMethod.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* 执行类的方法
*/
public static void doMethod() {
Class personClass = getPersonClass(3);
Person person = new Person();
try {
// public 无参数方法调用
Method getNameMethod = personClass.getMethod("getName");
String name = (String) getNameMethod.invoke(person);
System.out.println(name);
// public 有参数方法调用
Method setNameMethod = personClass.getMethod("setName", String.class);
setNameMethod.invoke(person, "hehe");
System.out.println((String) getNameMethod.invoke(person));
// 非public 无参数方法调用
Method getAgeMethod = personClass.getDeclaredMethod("getAge");
getAgeMethod.setAccessible(true);
int age = (int) getAgeMethod.invoke(person);
System.out.println(age);
// 非public 有参数方法调用
Method setAgeMethod = personClass.getDeclaredMethod("setAge", int.class);
setAgeMethod.setAccessible(true);
setAgeMethod.invoke(person, 12);
System.out.println((int) getAgeMethod.invoke(person));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 获取注解
*/
public static void getAnnotation() {
Class personClass = getPersonClass(3);
try {
Field field = personClass.getField("name");
MyAnnotation annotation = (MyAnnotation) field.getAnnotation(MyAnnotation.class);
System.out.println(annotation.MyNameValue());
Field ageField = personClass.getDeclaredField("age");
MyAnnotation ageAnnotation = (MyAnnotation) ageField.getAnnotation(MyAnnotation.class);
System.out.println(ageAnnotation.MyNameValue());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
MyAnnotation.java
package com.example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by hehelt on 16/8/4.
* <p>
* 自定义的注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
String MyNameValue() default "";
}
Person.java
package com.example;
/**
* Created by hehelt on 16/8/4.
*/
public class Person {
@MyAnnotation(MyNameValue = "heheLT")
public String name = "LT";
@MyAnnotation(MyNameValue = "heheLT")
private int age = 0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int getAge() {
return age;
}
private void setAge(int age) {
this.age = age;
}
}