反射的概念
java的放射机制:在程序运行时,程序有能力获取一个类的所有方法和属性;并且对于任意一个对象,可以调用它的任意方法或者获取其属性
通俗解析:java文件需要编译成.class文件才能被jvm加载使用,对象的.class数据在jvm里就是Class<T>;我们如果能拿到这个Class<T>对象,就能获取该Class<T>对应的对象类型,及在该类型声明的方法和属性值;还可以根据Class<T>创建相应的类型对象,通过Field,Method反过来操作对象
java相关类介绍
类名
描述
Class<T>
代表类的实体,在运行的Java应用程序中表示类或者接口
Field
类的成员变量(成员变量也称为类的属性)
Method
类的方法
Constructor<T>
类的构造方法
获取Class的三种方法
public Class<Example> getExample () {
Class<Example> clazz = Example.class;
return clazz;
}
复制代码
public Class<Example> getExampleByInstance () {
Example example = new Example();
Class<?> clazz = example.getClass();
return (Class<Example>)clazz;
}
复制代码
3通过Class.forName获取全路径指定类名的class
复制代码
public Class<Integer> getInteger () throws ClassNotFoundException {
Class<?> clazz = Class.forName("java.lang.Integer" );
return (Class<Integer>)clazz;
}
复制代码
JAVA反射API
public Constructor<?>[] getDeclaredConstructors()
public Constructor<T> getDeclaredConstructor (Class<?>... parameterTypes)
public native Class<? super T> getSuperclass ()
private Class<?>[] getInterfaces (boolean cloneArray)
public Class<?>[] getDeclaredClasses ()
public Method[] getDeclaredMethods () throws SecurityException
public Method getDeclaredMethod (String name, Class<?>... parameterTypes)
public Field[] getFields () throws SecurityException
public Field getField (String name)
复制代码
public Class<?> getReturnType()
public Class<?>[] getParameterTypes()
public Object invoke (Object obj, Object... args)
复制代码
//属性与obj相等则返回true
public boolean equals(Object obj)
//获得obj中对应的属性值
public Object get(Object obj)
//设置obj中对应属性值
public void set (Object obj, Object value)
复制代码
public T newInstance (Object... initargs)
复制代码
Class<Example> clazz = Example.class;
Example example = clazz.newInstance();
-----------------------------------------
public class Example {
private int value;
public Example () { }
public Example (Integer value) { this .value = value; }
static public void main (String[] args) throws Exception {
Class<Example> clazz = Example.class;
Constructor<Example> constructor = clazz.getConstructor(Integer.class);
Example example = constructor.newInstance(100 );
System.out.println(example.value);
}
}
复制代码
public class Example {
private int value , count;
static public void main (String[] args) throws Exception {
Class<Example> clazz = Example.class;
Field[] fs = clazz.getDeclaredFields();
Field value = clazz.getDeclaredField("value" );
Example example = clazz.newInstance();
value.setAccessible(true );
value.set(example,100 );
System.out.println(example.value);
}
}
复制代码
3由class获取Method,并反射调用实例方法
public class Example {
public static void main (String[] args) throws Exception {
Class<Example> clazz = Example.class;
Example example = clazz.newInstance();
Method[] methods = clazz.getDeclaredMethods();
Method method = clazz.getDeclaredMethod("hello" , String.class);
method.setAccessible(true );
method.invoke(example, "cscw" );
}
private void hello (String name) { System.out.println(name + " Hello!" ); }
}
-----
cscw Hello!
复制代码
反射机制应用的场景
1 动态拓展:假设有同一组类是实现相同的接口,并且类的加载方式不限制。当我们需要那种具体类实现的功能时,只需加载.class文件,并获取对应的Class<T>对象。可以由Class或者Constructor实例化对象instance;根据接口定义,可以获取Class<T>里的某一方法Method,并配合instance反射调用功能方法
2 Spring的IOC就是基于反射机制实现
3 JDK的动态代理
反射和JDK动态代理
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口。通过这个类和接口可以生成JDK动态代理类或动态代理对象
public interface InvocationHandler {
Object invoke (Object var1, Method var2, Object[] var3) throws Throwable ;
}
public class Proxy implements Serializable {
...
//根据interfaces 和InvocationHandler 生成代理对象
public static Object newProxyInstance (ClassLoader loader ,
Class <?>[] interfaces , InvocationHandler h )
...
}
复制代码
JDK的动态代理由Proxy和InvocationHandler实现;而被代理对象必须实现一个接口。代理对象由Proxy生成,可转为接口interface的实现类对象OBJ。当调用OBJ的方法时,则会触发InvocationHandler.invoke,参数依次为代理对象 ,Method对象 ,和方法Method所需的参数 。在invoke方法可以加入拓展的逻辑,如日志记录操作;并可以在invoke里利用反射的技术调用被代理对象方法
示例
public class ExampleFactory <T > implements InvocationHandler {
private T target;
public T bind (T obj) {
target = obj;
return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this );
}
复制代码
欢迎指正文中错误
关注公众号,一起交流
参考文章
近期评论