java反射机制详解

来源:互联网 发布:微信登录网络连接失败 编辑:程序博客网 时间:2024/06/03 17:04

反射:
1。可以于运行时加载,探知和使用编译期间完全未知的类。
2。程序在运行状态中, 可以动态加载一个只有名称的类, 对于任意一个已经加载的类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能调用他的任意一个方法和属性。
3。加载完类之后, 在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象), 这个对象包含了完整的类的结构信息,而且这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以被称之为:反射。
4。每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,通过该Class对象就可以访问到JVM中的这个类。
Java反射机制提供的功能:
1。在运行时判断任意一个对象所属的类
2。在运行时构造任意一个类的对象
3。在运行时判段任意一个类所具有的成员变量和方法
4。在运行时调用任一个对象的方法
5。在运行时创建新类对象
6。在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。
首先定义用于测试的类

class Type{    public int pubIntField;    public String pubStringField;    private int prvIntField;    public Type(){        Log("Default Constructor");    }    Type(int arg1, String arg2){        pubIntField = arg1;        pubStringField = arg2;        Log("Constructor with parameters");    }    public void setIntField(int val) {        this.prvIntField = val;    }    public int getIntField() {        return prvIntField;    }    private void Log(String msg){        System.out.println("Type:" + msg);    }}class ExtendType extends Type{    public int pubIntExtendField;    public String pubStringExtendField;    private int prvIntExtendField;    public ExtendType(){        Log("Default Constructor");    }       ExtendType(int arg1, String arg2){              pubIntExtendField = arg1;        pubStringExtendField = arg2;        Log("Constructor with parameters");    }    public void setIntExtendField(int field7) {        this.prvIntExtendField = field7;    }    public int getIntExtendField() {        return prvIntExtendField;    }    private void Log(String msg){        System.out.println("ExtendType:" + msg);    }}

1。获取类的Class对象
Class类的实例表示正在运行的java应用程序中的类和接口。获取Class对象有多种方式

  • getClass
Boolean var1 = true;Class<?> classType2 = var1.getClass();System.out.println(classType2);输出:class java.lang.Boolean
  • 运用.class语法
Class<?> classType4 = Boolean.class;System.out.println(classType4);输出:class java.lang.Boolean
  • 运用static method Class.forName()
Class<?> classType5 = Class.forName("java.lang.Boolean");System.out.println(classType5);输出:class java.lang.Boolean
  • 运用type语法
Class<?> classType3 = Boolean.TYPE;System.out.println(classType3);        输出:boolean

2。获取类的Fields

  • public Field getField(String name)
    返回一个 Field 对象,它反映此 Class 对象所表示的类或 接口的指定公共成员字段
  • public Field[] getFields()
    返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
  • public Field getDeclaredField(String name)
    返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
  • public Field[] getDeclaredFields()
    返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
Class<?> classType = ExtendType.class;// 使用getFields获取属性Field[] fields = classType.getFields();for (Field f : fields){    System.out.println(f);}System.out.println();// 使用getDeclaredFields获取属性fields = classType.getDeclaredFields();for (Field f : fields){    System.out.println(f);}
public int com.quincy.ExtendType.pubIntExtendFieldpublic java.lang.String com.quincy.ExtendType.pubStringExtendFieldpublic int com.quincy.Type.pubIntFieldpublic java.lang.String com.quincy.Type.pubStringFieldpublic int com.quincy.ExtendType.pubIntExtendFieldpublic java.lang.String com.quincy.ExtendType.pubStringExtendFieldprivate int com.quincy.ExtendType.prvIntExtendField

3。获取类的Method

  • public Method getMethod(String name, Class

Class<?> classType = ExtendType.class;Method[] methods = classType.getMethods();for (Method m : methods){    System.out.println(m);}System.out.println();// 使用getDeclaredMethods获取函数 methods = classType.getDeclaredMethods();for (Method m : methods){    System.out.println(m);}
输出:public void com.quincy.ExtendType.setIntExtendField(int)public int com.quincy.ExtendType.getIntExtendField()public void com.quincy.Type.setIntField(int)public int com.quincy.Type.getIntField()public final native void java.lang.Object.wait(long) throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionpublic boolean java.lang.Object.equals(java.lang.Object)public java.lang.String java.lang.Object.toString()public native int java.lang.Object.hashCode()public final native java.lang.Class java.lang.Object.getClass()public final native void java.lang.Object.notify()public final native void java.lang.Object.notifyAll()private void com.quincy.ExtendType.Log(java.lang.String)public void com.quincy.ExtendType.setIntExtendField(int)public int com.quincy.ExtendType.getIntExtendField()

4。获取类的Constructor

  • public Constructor getConstructor(Class
Constructor<?>[] constructors = classType.getConstructors();for (Constructor<?> m : constructors){    System.out.println(m);}System.out.println();// 使用getDeclaredConstructors获取构造器   constructors = classType.getDeclaredConstructors();for (Constructor<?> m : constructors){    System.out.println(m);}输出:public com.quincy.ExtendType()public com.quincy.ExtendType()com.quincy.ExtendType(int,java.lang.String)

5。新建类的实例

1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败.Class<?> classType = ExtendType.class;Object inst = classType.newInstance();System.out.println(inst);输出:Type:Default ConstructorExtendType:Default Constructorcom.quincy.ExtendType@d80be32、调用默认Constructor对象的newInstance方法Class<?> classType = ExtendType.class;Constructor<?> constructor1 = classType.getConstructor();Object inst = constructor1.newInstance();System.out.println(inst);输出:Type:Default ConstructorExtendType:Default Constructorcom.quincy.ExtendType@1006d75
3、调用带参数Constructor对象的newInstance方法Constructor<?> constructor2 =classType.getDeclaredConstructor(int.class, String.class);Object inst = constructor2.newInstance(1, "123");System.out.println(inst);输出:Type:Default ConstructorExtendType:Constructor with parameterscom.quincy.ExtendType@15e83f9

6。调用类的函数
通过反射获取类Method对象,调用Field的Invoke方法调用函数。

Class<?> classType = ExtendType.class;Object inst = classType.newInstance();Method logMethod = classType.<strong>getDeclaredMethod</strong>("Log", String.class);logMethod.invoke(inst, "test");输出:Type:Default ConstructorExtendType:Default Constructor<font color="#ff0000">Class com.quincy.ClassT can not access a member of class com.quincy.ExtendType with modifiers "private"</font><font color="#ff0000">上面失败是由于没有权限调用private函数,这里需要设置Accessible为true;</font>Class<?> classType = ExtendType.class;Object inst = classType.newInstance();Method logMethod = classType.getDeclaredMethod("Log", String.class);logMethod.setAccessible(true);logMethod.invoke(inst, "test");

7。设置/获取类的属性值
通过反射获取类的Field对象,调用Field方法设置或获取值

Class<?> classType = ExtendType.class;Object inst = classType.newInstance();Field intField = classType.getField("pubIntExtendField");intField.<strong>setInt</strong>(inst, 100);    int value = intField.getInt(inst);

四,动态创建代理类
代理模式:为其他对象提供一种代理以控制对这个对象的访问
代理模式的角色:
抽象角色:声明真实对象和代理对象的公共接口
代理角色:代理角色内部含有真实对象的引用,从而可以操作真实对象。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

  • java.lang.reflect.Proxy
    Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
  • InvocationHandler
    是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
    1。定义抽象角色
  public interface Subject {public void Request();}

2。定义真实角色

public class RealSubject implements Subject {@Overridepublic void Request() {// TODO Auto-generated method stubSystem.out.println("RealSubject");}}

3。定义代理角色

public class DynamicSubject implements InvocationHandler {private Object sub;public DynamicSubject(Object obj){this.sub = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubSystem.out.println("Method:"+ method + ",Args:" + args);method.invoke(sub, args);return null;}}

4。通过Proxy.newProxyInstance构建代理对象

RealSubject realSub = new RealSubject();InvocationHandler handler = new DynamicSubject(realSub);Class<?> classType = handler.getClass();Subject sub = (Subject)Proxy.newProxyInstance(classType.getClassLoader(),realSub.getClass().getInterfaces(), handler);System.out.println(sub.getClass()); 

5。通过调用代理对象的方法去调用真实角色的方法

sub.Request();
输出:class com.sun.proxy.$Proxy0Method:public abstract void realsubject.subject.Request(),Args:nullRealSubject
原创粉丝点击