JAVA中通过反射机制去访问字节码文件中的属性,方法,构造方法

一、访问字节码文件中的属性

通过如下代码可进行分析:

 //假设有一User类其里存放着public型变量name与非public型变量age
Class cla=Class.forName("User");//获取字节文件的地址
Object o=cla.newInstance();//通过该地址去实例化该字节文件
Field field1=cla.getDeclaredField("name");//获取该字节文件中的public属性
field1.set(o,"hyy");//进行属性的赋值
System.out.println(field1.get(o));//输出赋值后的属性值
Field field=cla.getDeclaredField("age");//获取该字节文件中的非public属性
field.setAccessible(true);//打破封装
field.set(o,20);//通过调用属性中的set方法去给属性赋值
System.out.println(field.get(o));//通过调用属性中的get方法去得该该属性的值

访问字节码文件中的属性,获取且赋值:从中可以看出通过反射机制去访问一个对象中的属性得先去得到这个对象所在的字节码文件地址,在通过该地址去newInstanace去创建这个对象然后通过该地址去调用getDeclaredField方法去获取对象中已存在的属性而后去通过调用该属性的set方法去给该属性赋值,在其中的传参中第一个参素即为对象名,第二个参数才为对象值。所以在给属性赋值的时候都逃不出对象的属性。即要先去实例化这个对象,上述的方法中只能访问的到public修饰的属性,也就是说除public修饰的属性外其他属性都该不了值,若想去强行赋值值能调用属性中的setAccessible(true)方法,这种方法叫做打破封装,也是反射机制中的一种缺点。值得注意的是,在这里若是单纯的获取属性不进行属性的赋值则无需去创建对象,若要进行对属性的赋值则需要去创建对象

二、访问字节码文件中的构造方法

//假设有一字节码文件mytest1里面存有有参构造,参数列别为string类型和int类型
Class cla=Class.forName("mytest1");
//调用字节码文件中的getDeclaredConstructor方法,实参列别格式为(数据类型.class),其中该数据类
//型为访问对应构造方法中的数据类型
Constructor cons=cla.getDeclaredConstructor(String.class,int.class);
//进行对象的创建及赋值
Object oo=cons.newInstance("zhangsan",20);
//进行打印结果
System.out.println(oo);

从中可看出若想访问字节码文件中的构造方法,则先得到这个对象所在的字节码文件的地址。后通过该变量去调用getDeclaredConstructor方法,且在该方法的实参列表中传入相对应的值,该值的形式以 数据类型.class的方式进行传输,其中 “ 数据类型” 为构造方法中形参列表的数据类型,想调用哪个构造方法则进行对应的传输即可。后通过调用newInstance去创建对象且进行相对应的赋值即可。其中若调用的是无参构造则有下述代码可见:

方式1:
Class cla=Class.forName("mytest1");
Constructor cons=cla.getDeclaredConstructor();
Object oo=cons.newInstance();
System.out.println(oo);
方式2:
Class cla=Class.forName("mytest1");
Object oo=cla.newInstance();
System.out.println(oo);

其中方式2这种省略了Constructor对象的创建从而直接去利用获取到的字节码文件直接去通过newInstance创建对象的方式,该方式虽说也可访问到其他类中的无参构造,但是这种方式是已过时的,在低版本jdk种若利用文本编译器去编译则会抛出异常。

三、访问字节码文件中的方法

Class cla=Class.forName("mytest1");//获取字节码文件地址
Object o=cla.newInstance();//创建对象
//假设该对象中有一fan1方法,其形参列表数据类型分别有String与int
Method met=cla.getDeclaredMethod("fan1",String.class,int.class);//定位对象中的那个方法
Object oo1=met.invoke(o,"zhangsan",20);//进行方法中形参列表的赋值
System.out.println(oo1);//打印其结果

其中访问方法与访问构造方法的步骤是大致相同的,其区别在于获取构造方法不需要进行传入方法名因为构造方法的方法名都是一样的,只需要传入数据类型即可。在后续调用该构造方法的时候也只需要调用newInstance方法进行传值即可不需要进行传对象,因为newInstance就是在创建对象的过程。值得注意的是在上述的通过访问构造方法的时候,要去重写一下toString方法,否者输出打印的值则是该对象的一个地址值。

以上均个人小白理解,如有错,望各位大侠能指出。

感谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值