java 反射 stream对象_JAVA基础知识之JVM-——使用反射生成并操作对象

Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法;可以获取构造器,由Constructor对象表示,调用Constructor对象的newInstance方法可以执行类对应的构造方法;可以获取成员变量,由Field对象表示,通过Field对象可以直接修改类的成员变量的访问权限和值。

创建对象

通过反射有两种方式创建对象

使用Class对象的newInstance(),这是最常用的方式,根据配置文件信息创建对象。

使用Class对象获取指定的Constructor对象,再由Constructor对象的newInstance创建类的对象。

调用方法

首先要获取类在JVM中对应的Class对象,通过类的Class对象的getMethod方法来获取类的方法,返回Method类型的对象,最后通过Method对象的invoke来执行类的方法。

下面的例子将演示从配置文件中读取数据来动态地创建对象,还通过配置文件信息来执行对象的setter来初始化对象。

1 packagejvmTest;2

3 importjava.io.FileInputStream;4 importjava.io.IOException;5 importjava.lang.reflect.Method;6 importjava.util.HashMap;7 importjava.util.Map;8 importjava.util.Properties;9

10 public classExtendedObjectPoolFactory {11 private Map objectPool = new HashMap<>();12 private Properties config = newProperties();13 public voidinit(String fileName) {14 try{15 FileInputStream fis = newFileInputStream(fileName);16 config.load(fis);17 } catch(IOException ex) {18 System.out.println("读取 " + fileName + " 异常");19 ex.printStackTrace();20 }21 }22 private Object createObject(String clazzName) throwsException {23 Class> clazz = Class.forName(clazzName);24 //使用clazz默认构造器创建对象

25 return clazz.newInstance();26 }27 //根据配置文件创建对象

28 public void initPool() throwsException {29 for(String name : config.stringPropertyNames()) {30 if (!name.contains("%")) {31 objectPool.put(name, createObject(config.getProperty(name)));32 }33 }34 }35

36 //根据配置文件来执行对象对应的set方法

37 public void initProperty() throwsException {38 for(String name : config.stringPropertyNames()) {39 if (name.contains("%")) {40 String[] objAndPro = name.split("%");41 //获取对象

42 Object target = getObject(objAndPro[0]);43 //构造setter方法名

44 String mtdName = "set"+ objAndPro[1].substring(0,1).toUpperCase() + objAndPro[1].substring(1);45 Class> targetClass = target.getClass();46 Method mtd = targetClass.getMethod(mtdName, String.class);47 mtd.invoke(target, config.getProperty(name));48 }49 }50 }51

52 publicObject getObject(String name) {53 returnobjectPool.get(name);54 }55

56 public static void main(String[] args) throwsException {57 ExtendedObjectPoolFactory epf = newExtendedObjectPoolFactory();58 epf.init("extObj.txt");59 epf.initPool();60 epf.initProperty();61 System.out.println(epf.getObject("a"));62 }63 }

上面程序第23行获取Class对象后在第25行使用默认的构造器动态创建出了对象,

如果要使用指定构造器,需要先获取Constructor对象,再使用Cronstructor对象的newInstance创建对象,像下面这样,

1 Constructor ctor = clazz.getConstructor(String.class);2 return ctor.newInstance("here is parameter for specific constructor");

第45行获取Class对象后,在46行通过Class对象获取指定要执行的方法(带一个参数),用Method对象表示,最后在47行调用Method对象的invoke可以执行类的指定方法

上面的例子使用下面的测试文件进行测试,

extObj.txt

1 a=javax.swing.JFrame2 b=javax.swing.JLabel3 a%title=Test title

输入结果,

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=Test title,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

View Code

访问成员变量

通过Class对象的getField方法可以访问指定的成员变量,调用继承自AccessableObject的setAccessable方法可以获得private成员变量的访问权限。

以下方法可以访问成员变量,

get(Object obj), 获取成员变量值。  如果是基本类型,直接使用类似 getInt(Object obj),  getChar(Object obj)的方式

set(Object obj), 设置成员变量值。 如果是基本类型,直接使用类似 setInt(Object, int val), setChar(Object obj, char c)的方式

下面演示访问成员变量,

1 packagejvmTest;2

3 importjava.lang.reflect.Field;4

5 classPerson {6 privateString name;7 private intage;8 publicString toString() {9 return "Person[name: "+name+", age: "+age+"]";10 }11 }12 public classFieldTest {13 public static void main(String[] args) throwsException {14 Person p = newPerson();15 Class clazz = Person.class;16 //getDeclaredFiled可以获取所有访问权限的成员变量

17 Field nameField = clazz.getDeclaredField("name");18 //true表示取消权限限制

19 nameField.setAccessible(true);20 nameField.set(p, "Tom");21 Field ageField = clazz.getDeclaredField("age");22 ageField.setAccessible(true);23 ageField.setInt(p, 18);24 System.out.println(p);25 }26 }

上面程序第20行使用的是set(), 而23行使用的是setInt(), 输出结果,

Person[name: Tom, age: 18]

操作数组

java.lang.reflect还包含一个Array类,可以动态地创建数组,设置元素的值,比较强大,主要方法有,

newInstance(..),创建数组,可以指定数组元素类型, 数组维度, 数组长度

get(...), 获取索引为index的元素,对于基本数据类型的数组,方法为getInt(...),  getChar(...) ...

set(...), 设置索引为index的元素,对于基本数据类型的数组,方法为setInt(...),  setChar(...) ...

下面演示用法,

1 packagejvmTest;2

3 importjava.lang.reflect.Array;4

5 public classArrayTest2 {6 public static voidmain(String[] args) {7 //创建三维数组

8 Object arr = Array.newInstance(String.class, 3, 4, 10);9 //获取index为2的元素,该元素是一个二维数组

10 Object arrObj = Array.get(arr, 2);11 //给二维数组index为2的元素赋值12 //二维数组的元素是一维数组,所以赋值也要用数组来赋值

13 Array.set(arrObj, 2, new String[] { "天王盖地虎", "宝塔镇河妖"});14 //获取二维数组指定index的元素(结果是一维数组)

15 Object anArr = Array.get(arrObj, 3);16 Array.set(anArr, 8, "野鸡闷头钻,哪能上天王山");17 //将arr强制转换为三维数组

18 String[][][] cast =(String[][][])arr;19

20 System.out.println(cast[2][2][0]);21 System.out.println(cast[2][2][1]);22 System.out.println(cast[2][3][8]);23 }24 }

输出如下,

1 天王盖地虎2 宝塔镇河妖3 野鸡闷头钻,哪能上天王山

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值