反射
来源
https://www.jianshu.com/p/9be58ee20dee
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java
语言的反射机制。
反射机制的相关类
类名 | 用途 |
---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。
方法 | 用途 |
---|
asSubclass(Class clazz) | 把传递的类的对象转换成代表其子类的对象 |
cast | 把对象转换成代表类或是接口的对象 |
getClassLoader() | 获得类的加载器 |
getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperclass() | 获得当前类继承的父类的名字 |
getInterfaces() | 获得当前类实现的类或是接口 |
方法 | 用途 |
---|
getField(String name) | 获得某个公有的属性对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
方法 | 用途 |
---|
getAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的公有注解对象 |
getAnnotations() | 返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的所有注解对象 |
getDeclaredAnnotations() | 返回该类所有的注解对象 |
方法 | 用途 |
---|
getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
方法 | 用途 |
---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
方法 | 用途 |
---|
isAnnotation() | 如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型则返回true |
isAnonymousClass() | 如果是匿名类则返回true |
isArray() | 如果是一个数组类则返回true |
isEnum() | 如果是枚举类则返回true |
isInstance(Object obj) | 如果obj是该类的实例则返回true |
isInterface() | 如果是接口类则返回true |
isLocalClass() | 如果是局部类则返回true |
isMemberClass() | 如果是内部类则返回true |
Field类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
setAccessible(boolean) | 设置方法的可访问性 |
Method类
Method代表类的方法。
方法 | 用途 |
---|
invoke(Object obj, Object… args) | 传递object对象及参数调用该对象对应的方法 |
setAccessible(boolean) | 设置方法的可访问性 |
速度较慢,不要使用Method
回调,推荐接口回调
Constructor类
Constructor代表类的构造方法。
方法 | 用途 |
---|
newInstance(Object... initargs) | 根据传递的参数创建类的对象 |
getDeclaringClass() | 返回一个用于描述类的对象 |
getExceptionTypes() | 返回一个描述方法抛出异常类型的Class对象数组(Constructor和Method) |
getModifiers() | 一个用于描述构造器,方法或域的修饰符的整型数值。使用Modifer 类中的方法可以分析这个返回值 |
getParameterTypes() | 获取参数类型(Constructor和Method) |
setAccessible(boolean) | 设置方法的可访问性 |
Modifier
返回值 | 方法 | 说明 |
---|
boolean | static isXxxx(int) | 传入getModifiers() 方法的返回值,判断是否是某种修饰符 |
String | static toString(int) | 通过getModifiers() 的值,返回对应的修饰符字符串表示 |
public static void test5() {
Class<?> t = Class.forName("cc.T");
int modifiers = t.getDeclaredMethod("getD").getModifiers();
String s = Modifier.toString(modifiers);
System.out.println(s);
}
AccessibleObject
返回值 | 方法 | 说明 |
---|
| static setAccessible(AccessibleObject[] array, boolean flag) | 批量设置Accessible |
其它方法用于继承
示例
private
方法与属性,需通过setAccessible()
方法来访问(在不受到安全管理器的控制时)
调用静态方法invoke
第一个参数填null
package cc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class A{
public static void main(String[] args) {
test4();
}
public static void test6(){
Class<?> aClass = Class.forName("cc.T");
Method p = aClass.getMethod("p");
p.invoke(null);
}
public static void test5(){
Class<?> t = Class.forName("cc.T");
T o1 = (T) t.newInstance();
Constructor<? extends T> constructor = o1.getClass().getDeclaredConstructor();
T o2 = constructor.newInstance();
}
public static void test4() {
Class<?> t = Class.forName("cc.T");
T o1 = (T) t.newInstance();
Method print = o1.getClass().getDeclaredMethod("print");
print.setAccessible(true);
print.invoke(o1);
}
public static void test3() {
T t = new T();
Class<? extends T> aClass = t.getClass();
Field d = aClass.getDeclaredField("d");
d.setAccessible(true);
d.setInt(t,56);
System.out.println(d.getInt(t));
}
private static void test2(){
T t = new T();
t.setD(23);
Class<? extends T> aClass = t.getClass();
Method getD = aClass.getDeclaredMethod("getD");
Method setD = aClass.getDeclaredMethod("setD", int.class);
Object invoke = getD.invoke(t);
System.out.println(invoke);
setD.invoke(t,55);
System.out.println(getD.invoke(t));
}
public static void test1(){
Class<?> t = Class.forName("cc.T");
T o1 = (T) t.newInstance();
o1.setD(23);
System.out.println(o1.getD());
}
}
class T{
public int a;
protected int b;
int c;
private int d;
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
public int getD() {
return d;
}
public void setD(int d) {
this.d = d;
}
private void print(){
System.out.println("Private Method");
}
public static void p(){
System.out.println("Static Method");
}
}
通过反射扩展数组
如果创建的数组一开始是Object
类型的,那么无法向下转型
public class A{
public static void main(String[] args){
int[] a = {2,4,5};
int[] b = (int[]) copyOfArray(a,6);
System.out.println("Length: "+b.length);
System.out.println(Arrays.toString(b));
}
public static Object copyOfArray(Object o,int newLength){
Class<?> cl = o.getClass();
if (!cl.isArray()) return null;
Class<?> componentType = cl.getComponentType();
int lenght = Array.getLength(o);
Object newArray = Array.newInstance(componentType,newLength);
System.arraycopy(o, 0, newArray, 0, Math.min(lenght, newLength));
return newArray;
}
}