Java学习day035 反射(二)在运行时使用反射分析对象、使用反射编写泛型数组代码、调用任意方法

本文深入探讨Java反射技术,包括在运行时使用反射分析对象,如查看对象数据域及内容;利用反射创建泛型数组;以及调用任意方法。文章详细介绍了相关API的使用,如`Field`的`get`方法,`Array`类的`newInstance`方法,以及`Method`的`invoke`方法。示例代码展示了如何实现通用的`toString`方法、扩展数组以及调用任意方法,强调了反射在程序设计中的灵活性与潜在风险。
摘要由CSDN通过智能技术生成

使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。

day035   反射(二)在运行时使用反射分析对象、使用反射编写泛型数组代码、调用任意方法


1.在运行时使用反射分析对象

在前面,已经知道如何查看任意对象的数据域名称和类型:

•获得对应的Class对象。

•通过Class对象调用getDeclaredFields。

下面将进一步查看数据域的实际内容。当然,在编写程序时,如果知道想要査看的域名和类型,查看指定的域是一件很容易的事情。而利用反射机制可以查看在编译时还不清楚的对象域。

查看对象域的关键方法是Field类中的get方法。如果f是一个Field类型的对象(例如,通过getDeclaredFields得到的对象),obj是某个包含f域的类的对象,f.get(obj)将返回一个对象,其值为obj域的当前值。这样说起来显得有点抽象,这里看一看下面这个示例的运行。

Employee harry=new Employee("Harry Hacker",35000,10,1,1989);
Class cl=harry.getClass();
//the class object representing Employee
Field f=cl.getDeclaredFieldC"name"):
//the name field of the Employee class
Object v=f.get(harry);
//the value of the name field of the harry object,i.e.,the String object "Harry Hacker"

实际上,这段代码存在一个问题。由于name是一个私有域,所以get方法将会抛出一个IllegalAccessException。只有利用get方法才能得到可访问域的值。除非拥有访问权限,否则Java安全机制只允许査看任意对象有哪些域,而不允许读取它们的值。

反射机制的默认行为受限于Java的访问控制。然而,如果一个Java程序没有受到安全管理器的控制,就可以覆盖访问控制。为了达到这个目的,需要调用Field、Method或Constructor对象的setAccessible方法。例如,

f.setAtcessible(true);//now OK to callf.get(harry);

setAccessible方法是AccessibleObject类中的一个方法,它是Field、Method和Constructor类的公共超类。这个特性是为调试、持久存储和相似机制提供的。稍后将利用它编写一个通用的toString方法。

get方法还有一个需要解决的问题。name域是一个String,因此把它作为Object返回没有什么问题。但是,假定我们想要查看salary域。它属于double类型,而Java中数值类型不是对象。要想解决这个问题,可以使用Field类中的getDouble方法,也可以调用get方法,此时,反射机制将会自动地将这个域值打包到相应的对象包装器中,这里将打包成Double。

当然,可以获得就可以设置。调用f.set(obj,value)可以将obj对象的f域设置成新值。

后面的程序1显示了如何编写一个可供任意类使用的通用toString方法。其中使用getDeclaredFileds获得所有的数据域,然后使用setAccessible将所有的域设置为可访问的。对于每个域,获得了名字和值。后面的程序2递归调用toString方法,将每个值转换成字符串。泛型toString方法需要解释几个复杂的问题。循环引用将有可能导致无限递归。因此,ObjectAnalyzer将记录已经被访问过的对象。另外,为了能够査看数组内部,需要采用一种不同的方式。

可以使用toString方法查看任意对象的内部信息。例如,下面这个凋叫:

ArrayList<Tnteger> squares=new ArrayList<>();
for(inti=1;i<=5;i++)
    squares.add(i*i);
System.out.println(new ObjectAnalyzer().toString(squares));

将会产生下时的打印结果:

java.util.ArrayList[elementData=classjava.1ang.Object[]{java.1ang.Integer[value=l][][],
java.1ang.Integer[value=4][][],java.1ang.Integer[value=9][][],java.1ang.I
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值