反射1——Class类与Java反射

通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。Java反射机制的功能过十分强大,在java.lang.reflect包中提供了该功能过的支持。

java.lang.reflect包的描述

提供类和接口,以获得关于类和对象的反射信息。在安全限制内,反射允许编程访问关于加载类的字段、方法和构造方法的信息,并允许使用反射字段、方法和构造方法对其底层对等项进行操作。

如果必需的 ReflectPermission 可用,则 AccessibleObject 允许抑制访问检查。

Array 提供动态创建和访问数组的静态方法。

此包中的类以及 java.lang.Class 可以适应以下应用程序的需要:调试程序、解释程序、对象检查程序、类浏览程序,以及服务(比如,Object Serialization 和 JavaBean,它们需要访问目标对象(基于其运行时类)的公共成员或给定类声明的成员)。

从以下版本开始:JDK1.1


众所周知,所有Java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。利用Class类返回的对象,我们可以访问该返回对象的描述信息。

通过反射可访问的主要描述信息
组成部分访问方法返回值类型说明
包路径getPackage()Package对象获得该类的存放路径
类名称getName()String对象获得该类的名称
继承类getSuperclass()Class对象获得该类的继承类
实现接口getInterfaces()Class型数组获得该类实现的所有接口

getConstructors()Constructor型数组获得所有权限为public的构造方法

getConstrucor(Class<?>..parameterTypes)Constructor对象获得权限为public的指定构造方法
构造方法getDeclaredConstructors()Constructor型数组获得所有构造方法,按声明顺序返回

getDeclaredConstructor(Class<?>..parameterTypes)Constructor对象获得指定构造方法

getMethods()Method型数组获得所有权限为public的方法

getMethods(String name,Class<?>...parameterTypes)
Method对象获得权限为public的指定方法
方法getDeclaredMethods()Method型数组
获得所有方法,按声明顺序返回

getDeclaredMethod(String name,Class<?>...parameterTypes)
Method对象
获得指定方法

getFields()
Field型数组获得所有权限为public的成员变量

getField(String name)
Field对象获得权限为public的指定成员变量
成员变量getDeclaredFields()Field型数组
获得所有成员变量,按声明顺序返回

getDeclaredField(String name)
Field对象
获得指定成员变量
内部类getClass()Class型数组获得所有权限为public的内部类

getDeclaredClass()Class型数组获得所有内部类
内部类的声明类getDeclaringClass()Class对象如果该类为内部类,则返回它的成员类,否则返回null








访问构造方法

有上表可以看出,通过一组访问方法来访问构造方法是,将返回Constructor类型的数组或对象。每个Constructor对象代表一个构造方法,利用Constructor对象可以操作相应的构造方法。

Constructor类常用方法
方法说明
isVarArgs()查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false
getParameterTypeset()按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型
getExceptionTypes()以Class数组的形式获得该构造方法可能抛出的异常类型
newInstance(Object....initatgs)通过该构造方法利用指定的参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法
setAccessible(boolean flag)如果该构造方法的权限为private,默认为不允许通过反射利用newInstance(Object...initargs)方法创建对象。
如果先执行该方法,并将入口参数设置为true,则允许创建
getModifiers()获得可以解析出该构造方法所采用修饰符的整数。

通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以以字符串的形式获得所有修饰符。

Modifier类中的常用方法解析
静态方法说明
isPublic(int mod)查看是否被public修饰符修饰,如果是则返回true,否则返回false
isProtected(int mod)查看是否被protected修饰符修饰,如果是则返回true,否则返回false
isPrivate(int mod)查看是否被private修饰符修饰,如果是则返回true,否则返回false
isStatic(ing mod)查看是否被static修饰符修饰,如果是则返回true,否则返回false
isFinal(int mod)查看是否被final修饰符修饰,如果是则返回true,否则返回false
isString(int mod)以字符串的形式返回所有修饰符
实例

创建一个Example类

package Reflect;
public class Example {
String s;
int i,i2,i3;

private Example(){}

protected Example(String s,int i){
this.s=s;
this.i=i;
}
public Example(String...strings)throws NumberFormatException{
if(0<strings.length)
i=Integer.valueOf(strings[0]);
if(1<strings.length)
i2=Integer.valueOf(strings[1]);
if(2<strings.length)
i3=Integer.valueOf(strings[2]);
}
public void print(){
System.out.println("s="+s);
System.out.println("i="+i);
System.out.println("i2="+i2);
System.out.println("i3="+i3);
}
}

再写一个测试类

package Reflect;

import java.lang.reflect.Constructor;

public class Test {

public static void main(String[] args) {
Example example = new Example("10", "20", "30");
Class<? extends Example> exampleC = example.getClass();

Constructor[] declaredConstructors = exampleC.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
Constructor<?> constructor = declaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[] parameterTypes = constructor.getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为:");
Class[] exceptionTypes = constructor.getExceptionTypes();
for (int j = 0; j < exceptionTypes.length; j++) {
System.out.println(" " + exceptionTypes[j]);
}
Example example2 = null;
while (example2 == null) {
try {
if (i == 2)
example2 = (Example) constructor.newInstance();
else if (i == 1)
example2 = (Example) constructor.newInstance("7", 5);
else {
Object[] parameters = new Object[] { new String[] {
"100", "200", "300" } };
example2 = (Example) constructor
.newInstance(parameters);
}
} catch (Exception e) {
System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
constructor.setAccessible(true);
}
}
if(example2!=null){
example2.print();
System.out.println();
}
}
}
}

访问成员变量

通过表1中的方法可以访问成员变量时,将返回Field类型的对象或数组。每个对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。

Field类的常用方法

方法说明
getName()获得该成员变量的名称
getType()获得表示该成员变量类型的Class对象
get(Object obj)获得指定对象obj中成员变量的值,返回值为Object型
set(Object obj,Object value)将指定对象obj中成员变量设置为value
getInt(Object obj)获得指定对象obj中类型为int的成员变量的值
setInt(Object obj,int i)将指定对象obj中类型为int的成员变量设置为i
getFloat(Object obj)获得指定对象obj中类型为float的成员变量的值
setFloat(Object obj,float f)将指定对象obj中类型为float的成员变量设置为f
getBoolean(Object obj)获得指定对象obj中类型为bolean的成员变量的值
setBoolean(Object obj,boolean z)将指定对象obj中类型为boolean的成员变量设置为z
setAccessible(boolean flag)此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量
getModifiers()获得可以解析出该成员变量所采取修饰符的整数
实例

创建一个Example_02类

package Reflect;
public class Example_02 {
int i;
public float f;
protected boolean b;
private String s;
}

再创建一个Test2类

package Reflect;
import java.lang.reflect.*;
public class Test_02 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Example_02 example = new Example_02();
Class exampleC = example.getClass();
// 获得所有成员变量
Field[] declaredFields = exampleC.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i]; // 遍历成员变量
// 获得成员变量名称
System.out.println("名称为:" + field.getName());
Class fieldType = field.getType(); // 获得成员变量类型
System.out.println("类型为:" + fieldType);
boolean isTurn = true;
while (isTurn) {
// 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
try {
isTurn = false;
// 获得成员变量值
System.out.println("修改前的值为:" + field.get(example));
// 判断成员变量的类型是否为int型
if (fieldType.equals(int.class)) {
System.out.println("利用方法setInt()修改成员变量的值");
field.setInt(example, 168); // 为int型成员变量赋值
// 判断成员变量的类型是否为float型
} else if (fieldType.equals(float.class)) {
System.out.println("利用方法setFloat()修改成员变量的值");
// 为float型成员变量赋值
field.setFloat(example, 99.9F);
// 判断成员变量的类型是否为boolean型
} else if (fieldType.equals(boolean.class)) {
System.out.println("利用方法setBoolean()修改成员变量的值");
// 为boolean型成员变量赋值
field.setBoolean(example, true);
} else {
System.out.println("利用方法set()修改成员变量的值");
// 可以为各种类型的成员变量赋值
field.set(example, "MWQ");
}
// 获得成员变量值
System.out.println("修改后的值为:" + field.get(example));
} catch (Exception e) {
System.out.println("在设置成员变量值时抛出异常,"
+ "下面执行setAccessible()方法!");
field.setAccessible(true); // 设置为允许访问
isTurn = true;
}
}
System.out.println();
}
}
}


访问方法

Method类的常用方法
方法说明
getName()获得该方法的名称
getParameterTypes()按照声明顺序以Class数组的形式获得该方法的各个参数的类型
getReturnType()以Class对象的形式获得该方法的返回值的类型
getExceptionTypes()以Class数组的形式获得该方法可能抛出异常的类型
invoke(Object obj,Object...args)利用指定参数args执行指定对象obj中的该方法,返回值为Object类型
isVarArgs()查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false
getModifiers()获得可以解析出该方法所采用修饰符的整数


实例

首先创建一个Example_03类

public class Example_03 {
static void staticMethod() {
System.out.println("执行staticMethod()方法");
}

public int publicMethod(int i) {
System.out.println("执行publicMethod()方法");
return i * 100;
}

protected int protectedMethod(String s, int i)
throws NumberFormatException {
System.out.println("执行protectedMethod()方法");
return Integer.valueOf(s) + i;
}

private String privateMethod(String... strings) {
System.out.println("执行privateMethod()方法");
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < strings.length; i++) {
stringBuffer.append(strings[i]);
}
return stringBuffer.toString();
}
}

在创建一个Test3类

import java.lang.reflect.*;


public class Test3 {
public static void main(String[] args) {
Example_03 example = new Example_03();
Class exampleC = example.getClass();

// 获得所有方法
Method[] declaredMethods = exampleC.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i]; // 遍历方法
System.out.println("名称为:" + method.getName()); // 获得方法名称
System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
System.out.println("入口参数类型依次为:");
// 获得所有参数类型
Class[] parameterTypes = method.getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.println(" " + parameterTypes[j]);
}
// 获得方法返回值类型
System.out.println("返回值类型为:" + method.getReturnType());
System.out.println("可能抛出的异常类型有:");
// 获得方法可能抛出的所有异常类型
Class[] exceptionTypes = method.getExceptionTypes();
for (int j = 0; j < exceptionTypes.length; j++) {
System.out.println(" " + exceptionTypes[j]);
}
boolean isTurn = true;
while (isTurn) {
// 如果该方法的访问权限为private,则抛出异常,即不允许访问
try {
isTurn = false;
if("staticMethod".equals(method.getName()))
method.invoke(example); // 执行没有入口参数的方法
else if("publicMethod".equals(method.getName()))
System.out.println("返回值为:"
+ method.invoke(example, 168)); // 执行方法
else if("protectedMethod".equals(method.getName()))
System.out.println("返回值为:"
+ method.invoke(example, "7", 5)); // 执行方法
else if("privateMethod".equals(method.getName())) {
Object[] parameters = new Object[] { new String[] {
"M", "W", "Q" } }; // 定义二维数组
System.out.println("返回值为:"
+ method.invoke(example, parameters));
}
} catch (Exception e) {
System.out.println("在执行方法时抛出异常,"
+ "下面执行setAccessible()方法!");
method.setAccessible(true); // 设置为允许访问
isTurn = true;
}
}
System.out.println();
}
}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值