java 抽象 反射_Java的反射

Java的反射

Class类

在此之前,我们必须知道一句话,“java之中的一切都可以看作一个对象”。类是对象的抽象,而Class则是类的抽象,即任何一个类都有唯一的一个Class的实例对象。另外注意区别Class类和class关键字。我们知道对象是用来封装和记录数据的。而类的结构信息又是一种数据,当类加载到JVM内存中,类的结构信息肯定不是混乱的,所以就需要Class类的对象来记载其他类的结构信息。Class类下面有很多方法,例如getConstructors() (包括其一些相似作用的方法这里以及后面不再列举,例如getDeclaredConstructor()等等),getFields(),getMethods();而它们会分别返回Constructor类型、Filed类型、Method类型的对象或者数组。Class类的构造方法是私有的,当一个类被加载时,JVM(java虚拟机)会自动通过Class的私有构造方法实例化一个Class对象,而我们没有办法通过Class的构造方法去实例化Class。而我们可以通过以下三种方法来获得Class的实例化对象;

Class.forName("具体路径 包名.类名"); //同一包下可以只写类名

类名.class;

对象.getClass();

获得了Class的实例化对象,我们就可以获得类的很多信息,例如权限修饰符,参数列表,类名,成员变量,成员方法等等。

问:什么是Java的反射?

答:Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态语言的一个关键性质。

问:Java反射有什么作用呢?

答:假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。

Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。

另外,因为利用反射执行方法时,方法名都是变量,即可以通过其他地方传进来,从而达到动态的目的。

Constructor类

每个Constructor对象都代表一个构造方法(注意仅仅是代表,而不是相同,实质上Constructor类的对象只是记载了某个类的构造方法的结构信息,下面的Method类、Field类也是一样的,不赘述),利用Constructor对象可以操作相应的构造方法。下面时Constructor类常用的方法以及它的作用;

isVarArgs(),查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false;方法原型:public boolean isVarArgs();

getName(),以字符串的形式返回该构造方法的名字。方法原型:public String getName();

getParameterTypes(),按照声明顺序以Class数组的形式获得该构造方法的各个参数类型。方法原型:public Class>[] getParameterTypes();

getExceptionTypes(),以Class数组的形式获得该构造方法可能抛出的异常类型。方法原型:public Class>[] getExceptionTypes();

newInstance(),通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法。函数原型:public T newInstance(Object... initargs),T表示返回的是一个Objec类的对象;

注:Class.newInstance和Constructor.newInstance的有区别;Constructor的该方法能够使用有参数的构造方法,而Class下的该方法只能够使用无参默认构造方法。

setAccessible(),如果该构造方法的权限为private,默认不允许通过反射利用newInstance()方法创建对象;如果先执行该方法并将入口参数设为true,则允许创建。方法原型:public void setAccessible(boolean flag);

getModifiers(),获得可以解析出该构造方法所采用的修饰符的整数(利用Modifier类下的toString方法可以转换成字符串)。方法原型:public int getModifiers()。

下面介绍几个Modifier类常用的方法;

isPublic(int mod);

isProtected(int mod);

isPrivate(int mod);

isStatic(int mod);

isFinal(int mod);

toString(int mod);

这几种方法的作用都显而易见,不再赘述。

下面看代码示例:

//代码示例 Main类

import java.lang.reflect.*;

public class Main_01 {

public static void main(String[] args) {

Example_01 example = new Example_01("10", "20", "30");

Class extends Example_01> 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_01 example2 = null;

while (example2 == null) {

try {

if (i == 2)

example2 = (Example_01) constructor.newInstance();

else if (i == 1)

example2 = (Example_01) constructor.newInstance("7", 5);

else {

Object[] parameters = new Object[] { new String[] {

"100", "200", "300" } };

example2 = (Example_01) constructor

.newInstance(parameters);

}

} catch (Exception e) {

System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");

constructor.setAccessible(true);

}

}

if(example2!=null){

example2.print();

System.out.println();

}

}

}

}

//代码示例 Example类

public class Example_01 {

String s;

int i, i2, i3;

private Example_01() {

}

protected Example_01(String s, int i) {

this.s = s;

this.i = i;

}

public Example_01(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);

}

}

这是运行结果截图:

13dcefbd36b6c918c3f7dde6eed9a353.png

Filed类

每个Field对象都代表一个成员变量,利用Field对象可以操控相应的成员变量。下面是Field类的一些常用的方法以及作用;

getName(),获得该成员变量的名称。方法原型:public String getName();

getType(),获得表示该成员变量类型的Class对象。方法原型:public Class> getType();

getModifiers(),获得可以解析出该成员变量所采用修饰符的整数。方法原型:public int getModifiers();

get(Object obj),获得指定对象obj中成员变量的值,返回类型为Object型。方法原型:public Object get(Object obj);

set(Object obj,Object value),将指定对象obj中成员变量的值设定为value;

还有具体到各种类型的get set方法,不再一一介绍。另外说明:Object对象指的是已经实例化的反射对象。

下面是代码示例:

//代码示例 Main类

import java.lang.reflect.*;

public class Main_02 {

public static void main(String[] args) {

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();

}

}

}

//代码示例 Example类

public class Example_02 {

int i;

public float f;

protected boolean b;

private String s;

}

下面是运行结果:

a03cbe5f8beed07b7714b45335fbaec1.png

Method类

每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。下面是Method类的一些常用的方法以及作用;

getName(),获得该方法的名称。方法原型:public String getName();

getParameterTypes(),按照声明的顺序以Class数组的形式获得该方法的各个参数的类型。方法原型:public Class>[] getParameterTypes();

getReturnType(),以Class对象的形式返回该方法的返回类型。方法原型:public Class> getReturnType();

getExceptionTypes(),以Class数组的形式获得该方法可能抛出的异常。方法原型:public Class> getExceptionTypes();

invoke(Object obj,Object···args),利用指定参数args执行指定对象obj中的该方法,返回值类型为Object型。方法原型:public Object invoke(Object obj, Object... args);

isVarArgs(),同Constructor;

getModifiers(),同上。

下面是代码示例:

//代码示例 Main类

import java.lang.reflect.*;

public class Main_03 {

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();

}

}

}

//代码示例 Example

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();

}

}

下面是运行结果图:

8412567279b545dfc72b8e5ac2922486.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值