Java反射机制

1.概念:

   运行时,对任意类,都能知道这个类的所有属性和方法;对任意一对象,都能够调用它的每个方法和属性;这种动态获取、调用的功能称为Java语言的反射机制。

2.实现:

Java反射相关的API在包java.lang.reflect中。

Member接口

该接口可以获取有关类成员(域或者方法)或者构造函数的信息。

AccessibleObject类

该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

Array类

该类提供动态地生成和访问JAVA数组的方法。

Constructor类

提供一个类的构造函数的信息以及访问类的构造函数的接口。

Field类

提供一个类的域的信息以及访问类的域的接口。

Method类

提供一个类的方法的信息以及访问类的方法的接口。

Modifier类

提供了 static 方法和常量,对类和成员访问修饰符进行解码。

Proxy类

提供动态地生成代理类和类实例的静态方法。

1)获取类的Class对象

   Class类的实例表示正在运行的 Java应用程序中的类和接口。获取类的Class对象有多种方式(此处以Boolean类为例):

调用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

运用静态方法 Class.forName()

Class<?> classType5 = Class.forName("java.lang.Boolean");

System.out.println(classType5);

输出:class java.lang.Boolean

运用primitive wrapper classes的TYPE 语法

这里返回的是原生类型,和Boolean.class返回的不同

Class<?> classType3 = Boolean.TYPE;

System.out.println(classType3);

输出:bool

2)获取类的Fields

   可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。JAVA的Class<T>类提供了几个方法获取类的属性

public Field getField(Stringname)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段

public Field[] getFields()

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段

public Field getDeclaredField(Stringname)

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段

public Field[] getDeclaredFields()

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有指定已声明字段

3)获取类的Method

   通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法。Class<T>类提供了几个方法获取类的方法。

public Method getMethod(String name,Class<?> parameterTypes)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法

public Method[] getMethods()

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口,包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法

public Method getDeclaredMethod(Stringname,Class<?> parameterTypes)

返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口指定的已声明方法

public Method[] getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法

4)获取类的Constructor

   通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例。Class<T>类提供了几个方法获取类的构造器。

public Constructor<T> getConstructor(Class<?> parameterTypes)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法

public Constructor<?>[] getConstructors()

返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法

public Constructor<T> getDeclaredConstructor(Class<?> parameterTypes)

返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法

public Constructor<?>[] getDeclaredConstructors()

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法

5)新建类的实例

   通过反射机制创建新类的实例,有几种方法可以创建

用无参Constructor

1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败.

Class<?> classType = ExtendType.class;

Object inst = classType.newInstance();

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Default Constructor

com.quincy.ExtendType@d80be3

 

2、调用默认Constructor对象的newInstance方法

Class<?> classType = ExtendType.class;

Constructor<?> constructor1 = classType.getConstructor();

Object inst = constructor1.newInstance();

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Default Constructor

com.quincy.ExtendType@1006d75

调用有参Constructor

3、调用带参数Constructor对象的newInstance方法

Constructor<?> constructor2 =

classType.getDeclaredConstructor(int.class, String.class);

Object inst = constructor2.newInstance(1, "123");

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Constructor with parameters

com.quincy.ExtendType@15e83f9

6)调用类的函数

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

7)设置/获取类的属性值

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

3.代码

  Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
1).得到某个对象的属性:

public ObjectgetProperty(Object owner, String fieldName)throws Exception {
    ClassownerClass = owner.getClass();
    Fieldfield = ownerClass.getField(fieldName);
    Objectproperty = field.get(owner);
    return property;
}

2).得到某个类的静态属性:

public ObjectgetStaticProperty(String className, String fieldName)throws Exception {
    ClassownerClass = Class.forName(className);
    Fieldfield = ownerClass.getField(fieldName);
    Objectproperty = field.get(ownerClass);
    return property;
}

3).执行某对象的方法:

public ObjectinvokeMethod(Object owner, String methodName, Object[] args)throws Exception {
    ClassownerClass = owner.getClass();
    Class[]argsClass = newClass[args.length];
    for (int i = 0, j = args.length; i < j; i++) {
        argsClass[i]= args[i].getClass();
    }
    Methodmethod = ownerClass.getMethod(methodName, argsClass);
    return method.invoke(owner,args);
}

4).执行某个类的静态方法:

public ObjectinvokeStaticMethod(String className, String methodName,Object[] args)throws Exception {
    ClassownerClass = Class.forName(className);
    Class[]argsClass = newClass[args.length];
    for (int i = 0, j = args.length; i < j; i++) {
        argsClass[i]= args[i].getClass();
    }
    Methodmethod = ownerClass.getMethod(methodName, argsClass);
    return method.invoke(null, args);
}

基本的原理和实例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。


5).新建实例:

public ObjectnewInstance(String className, Object[] args)throws Exception {
    ClassnewoneClass = Class.forName(className);
    Class[]argsClass = newClass[args.length];
    for (int i = 0, j = args.length; i < j; i++) {
        argsClass[i]= args[i].getClass();
    }
    Constructorcons = newoneClass.getConstructor(argsClass);
    return cons.newInstance(args);
}

这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。


6).判断是否为某个类的实例:

public boolean isInstance(Object obj, Classcls) {
    return cls.isInstance(obj);
}

7).得到数组中的某个元素:

public ObjectgetByArray(Object array,int index) {
    return Array.get(array, index);
}

转自:http://www.cnblogs.com/devinzhang/archive/2012/02/07/2341315.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值