JAVA反射
反射
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
功能
- 在运行时构造任意一个类的对象。
- 在运行时获取任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法(属性)。
- 生成动态代理。
实现(java.lang.reflect)
- Class 类:反射的核心类,可以获取类的属性,方法等信息。
- Field 类:Java.lang.reflect 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
- Method 类:Java.lang.reflect 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
- Constructor 类:java.lang.reflect 包中的类,表示类的构造方法。
// 创建一个类
public static class MyObject {
// protected 无法获取
MyObject() {
}
// public 可以获取
public MyObject(String name) {
}
// private 无法获取
private MyObject(int age) {
}
}
// 获取Class对象
Class<MyObject> clazz = MyObject.class;
// 1. 获取所有的Public构造器
Constructor<?>[] constructors = clazz.getConstructors();
// Constructors=[public tiny.wong.ConstructorTest$MyObject(java.lang.String)]
System.out.println("Constructors="+ Arrays.toString(constructors));
// 2. 获取指定参数类型的构造器
Constructor constructor = clazz.getConstructor(new Class[]{String.class});
Constructor constructor = constructors[0];
// 参数个数
int parameterCount = constructor.getParameterCount();
// 参数类型
Class[] parameterTypes = constructor.getParameterTypes();
// 访问修饰符
int modifiers = constructor.getModifiers();
// 获取方法注解
Annotation[] annotations = constructor.getAnnotations();
Annotation annotation = constructor.getAnnotation(null);
// 获取参数注解
constructor.getParameterAnnotations();
// 创建对象
try {
// newInstance 的参数是可变参数列表.
MyObject name = (MyObject) constructor.newInstance("name");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Son son = new Son();
Class clazz = Son.class;
// 1.1 获取所有的Public方法(包含父类)
Field[] fields = clazz.getFields();
// 1.2 获取指定的名称的Public Field
try {
Field theField = clazz.getField("fieldName");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 1.3 获取当前类的所有成员变量(不含父类)
Field[] declaredFields = clazz.getDeclaredFields();
// 1.4 获取当前类的指定成员变量(不含父类)
try {
Field theField1 = clazz.getDeclaredField("fieldName");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 2. Filed 的相关操作
Field field = fields[0];
// 2.1 变量名字
String filedName = field.getName();
// 2.2 变量类型
Class<?> type = field.getType();
try {
// 2.3 变量值
Object o = field.get(son);
// 2.4 设置成员变量的值
field.set(son, null);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 2.5 变量注解
Annotation[] annotations = field.getAnnotations();
Annotation[] declaredAnnotations = field.getDeclaredAnnotations();
Annotation annotation = field.getAnnotation(null);
// 2.6 变量的访问修饰符
int modifiers = field.getModifiers();
Son son = new Son();
Class clazz = Son.class;
// 获取私有属性
try {
Field name = clazz.getDeclaredField("name");
// 调用 setAccessible()方法会关闭指定类 Field 实例的反射访问检查
// 如果不进行设置, 可能会访问不到.
name.setAccessible(true);
// 获取属性值
Object value = name.get(son);
// 设置属性值
name.set(son, null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Son son = new Son();
Class clazz = Son.class;
// 1. 获取Method对象.
// 1.1 获取所有的Public方法(含父类)
Method[] methods = clazz.getMethods();
// 1.2 获取当前类所有的方法(不含父类)
Method[] declaredMethods = clazz.getDeclaredMethods();
// 1.3 获取指定方法.规则和上面一样.
try {
Method method = clazz.getMethod("method", null);
Method method1 = clazz.getDeclaredMethod("method", null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Method method = methods[0];
// 2. 方法名
String name = method.getName();
// 3. 方法返回值类型
Class<?> returnType = method.getReturnType();
// 4. 方法参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
// 5. 方法调用
try {
method.invoke(son, null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// 6. 方法注解
Annotation[] annotations = method.getAnnotations();
Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
method.getDeclaredAnnotation(null);
Son son = new Son();
Class clazz = Son.class;
try {
// 获取私有方法, 只能通过getDeclaredMethod,不能使用getMethod因为后者只能获取到Public修饰的方法.
Method test = clazz.getDeclaredMethod("test", new Class[]{String.class});
// 设置访问屏蔽反射访问检查
test.setAccessible(true);
// 调用方法
test.invoke(son, "test");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
public class GetterAndSetterDemo {
public static void testGetterAndSetter() {
Son son = new Son();
Class clazz = Son.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println("MName=" + method + " is Setter=" + isSetter(method));
System.out.println("MName=" + method + " is Getter=" + isGetter(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;
}
if (!void.class.equals(method.getReturnType())) {
return false;
}
return true;
}
}
Son son = new Son();
Class clazz = Son.class;
// 1. 方法注解
Method[] methods = clazz.getMethods();
Annotation[] annotations = methods[0].getAnnotations();
for (Annotation anno : annotations) {
if (anno instanceof Deprecated) {
System.out.println("Method Deprecated");
}
}
// 2. 变量注解
Field[] fields = clazz.getFields();
Annotation[] annotations1 = fields[0].getAnnotations();
for (Annotation anno : annotations1) {
if (anno instanceof Deprecated) {
System.out.println("Method Deprecated");
}
}
public static void testArray() {
// Java 反射机制通过 java.lang.reflect.Array 这个类来处理数组
// 1. 创建一个数组
int[] intArray = (int[]) Array.newInstance(int.class, 4);
// 2. 设置数组元素值
Array.set(intArray, 0, 0);
Array.set(intArray, 1, 1);
// 3. 获取元素值
Array.get(intArray, 0);
Array.get(intArray, 1);
// 4. 获取数组的成员类型
Class aClass = intArray.getClass();
Class componentType = aClass.getComponentType();
// 获取数组的Class
Class clazz1 = String[].class;
try {
// 在JVM中I代表int, [ 表示是数组.比如 "[Ljava.lang.String;"
Class clazz2 = Class.forName("[I");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 注意基本数据类型的Class不能直接用I或者int配合Class.forName来获取
}
国鑫感谢留意本博客!

浙公网安备 33010602011771号