今天项目中遇到了一个问题,要调用一个类,并获取这个类的属性进行赋值然后将这个类传递到方法中做为参数。

实际操作时才发现,这个类中的字段属性是私有的,不能进行赋值!没有提供公有的方法。而这个类又是打包成jar给我的,我还不能更改它的代码,以至于想手动给它写个set方法都是问题。后来想到用反射可以解决这个问题,于是试了一下,果然!

反射看来根本不区分是否是private的,调用本身的私有方法是可以的,但是调用父类的私有方法则不行,纠其原因很有可能是因为getDeclaredMethod方法和getMethod方法并不会查找父类的私有方法,自己写递归可以解决,不过利用反射来做的话性能不会太好。

我们来看下面这个代码。

  1. Field[] fields = obj.getDeclaredFields();
  2. for (int i = 0; i < fields.length; i++) {
  3. fields[i].setAccessible(true);
  4. for (int j = 0; j < args.length; j++) {
  5. String str = args[j];
  6. String strs[] = str.split(",");
  7. if (strs[0].equals(fields[i].getName())) {
  8. fields[i].set(object, strs[1]);
  9. break;
  10. }
  11. }
  12. }
  1. fields[i].setAccessible(true);

这句话是关键。看它的表面英文意思是设置可进入可访问为:true。编程意思大家猜想也应该知道了。

通过查看JDK的源码:

  1. public void setAccessible(boolean flag) throws SecurityException {
  2. SecurityManager sm = System.getSecurityManager();
  3. if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
  4. setAccessible0(this, flag);
  5. }

我们可以看到它是通过SecurityManager来管理权限的,我们可以启用java.security.manager来判断程序是否具有调用setAccessible()的权限。默认情况下,内核API和扩展目录的代码具有该权限,而类路径或通过URLClassLoader加载的应用程序不拥有此权限。例如:当我们以这种方式来执行上述程序时将会抛出异常

  1. java.security.AccessControlException:   access   denied

一般情况下,我们并不能对类的私有字段进行操作,但有的时候我们又必须有能力去处理这些字段,这时候,我们就需要调用AccessibleObject上的setAccessible()方法来允许这种访问,而由于反射类中的Field,Method和Constructor继承自AccessibleObject,因此,通过在这些类上调用setAccessible()方法,我们可以实现对这些字段的操作。

我们来看看这个ACCESS_PERMISSION里面究竟怎么处理的:

  1. static final private java.security.Permission ACCESS_PERMISSION =
  2. new ReflectPermission("suppressAccessChecks");

查找JDK帮助文档可以看到详细解释:

public final class ReflectPermissionextends BasicPermission

反射操作的 Permission 类。ReflectPermission 是一种指定权限,没有动作。当前定义的唯一名称是suppressAccessChecks,它允许取消由反射对象在其使用点上执行的标准 Java 语言访问检查 - 对于 public、default(包)访问、protected、private 成员。

下表提供了允许权限的简要说明,并讨论了授予代码权限的风险。

权限目标名称 权限允许的内容 允许此权限的风险

suppressAccessChecks

能够访问类中的字段和调用方法。注意,这不仅包括 public、而且还包括 protected 和 private 字段和方法。

存在的风险是,通常不可用的信息(也许是保密信息)和方法可能会接受恶意代码访问。

这里就一点了然了。fields.setAccessible(true);的实际作用就是使权限可以访问public,protected,private的字段!

是不是很爽呢。当然这种方法破坏了JAVA原有的权限体系。所以不到万不得已,还是少用,反射的效率毕竟不是那么高滴。

好,知道了这个我们再来写一个通用的万能方法,只是传递相应的类,字段名称和值,我们在方法内部将其反射并进行实例化。然后进行相应字段的赋值。由于我只用到了字段。你可以加上其它的东东。嗯。这个好玩。

  1. package unit.sms;
  2. public class Smss {
  3. private String destID;
  4. private String content;
  5. private String mobile;
  6. public String getDestID() {
  7. return destID;
  8. }
  9. public String getContent() {
  10. return content;
  11. }
  12. public String getMobile() {
  13. return mobile;
  14. }
  15. }
  1. package com.sinoglobal.utils;
  2. import java.lang.reflect.Field;
  3. import com.jasson.mas.api.smsapi.Sms;
  4. /**
  5. * 反射的通用工具类
  6. *
  7. * @author lz
  8. *
  9. */
  10. public class ReflectionUtils {
  11. /**
  12. * 用于对类的字段赋值,无视private,project修饰符,无视set/get方法
  13. * @param c 要反射的类
  14. * @param args 类的字段名和值 每个字段名和值用英文逗号隔开
  15. * @return
  16. */
  17. @SuppressWarnings("unchecked")
  18. public static Object getInstance(Class c, String... args) {
  19. try {
  20. Object object = Class.forName(c.getName()).newInstance();
  21. Class<?> obj = object.getClass();
  22. Field[] fields = obj.getDeclaredFields();
  23. for (int i = 0; i < fields.length; i++) {
  24. fields[i].setAccessible(true);
  25. for (int j = 0; j < args.length; j++) {
  26. String str = args[j];
  27. String strs[] = str.split(",");
  28. if (strs[0].equals(fields[i].getName())) {
  29. fields[i].set(object, strs[1]);
  30. break;
  31. }
  32. }
  33. }
  34. return object;
  35. } catch (IllegalAccessException e) {
  36. e.printStackTrace();
  37. } catch (ClassNotFoundException e) {
  38. e.printStackTrace();
  39. } catch (InstantiationException e) {
  40. e.printStackTrace();
  41. }
  42. return null;
  43. }
  44. public static void main(String[] args) {
  45. Object object = getInstance(Smss.class, "destID,08340001", "mobile,13408340000", "content,ReYo测试数据。");
  46. Smss sms = (Smss) object;
  47. System.out.println("短信内容:" + sms.getContent());
  48. System.out.println("手机号码:" + sms.getMobile());
  49. System.out.println("尾号:" + sms.getDestID());
  50. }
  51. }

控制台输出:

短信内容:ReYo测试数据。
手机号码:13408340000
尾号:08340001

fields.setAccessible(true);的使用可能大家都会,但我们要做的是,知其然,知其所以然。

看JDK的源码,无疑是学习和解决此方法的最佳途径。

java使用反射强制给private字段赋值的更多相关文章

  1. java高级编程-使用反射强制给private字段赋值

    转自:http://blog.csdn.net/yaerfeng/article/details/7103397 今天项目中遇到了一个问题,要调用一个类,并获取这个类的属性进行赋值然后将这个类传递到方 ...

  2. Java 使用反射拷贝对象一般字段值

    在<Java解惑>上面看到第八十三例--诵读困难者,要求使用非反射实现单例对象的拷贝.查阅了部分资料,先实现通过反射拷贝对象. 1. 编写需要被拷贝的对象Person package co ...

  3. 通过Field (反射)给私有字段赋值

    public class Person { public String name; public char sex; private int age; public String getName() ...

  4. java 利用反射机制,获取实体所有属性和方法,并对属性赋值

    一个普通的实体Person: private int id; private String name; private Date createdTime;...//其它字段// get set方法 . ...

  5. Java反射 - 简单的给Bean赋值和取值

    由于项目的实际需要,所以利用java反射原理写了一个简单给bean赋值和取值通用的类,在此记录下方便自己日后用到,也为需要的兄弟提供个参考例子. 工具类BeanRefUtil:   package c ...

  6. Java基础-反射(reflect)技术详解

    Java基础-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类加载器 1>.JVM 类加载机制  如下图所示,JVM类加载机制分为五个部分 ...

  7. 如何解决CRUD操作中与业务无关的字段赋值

    提高效率一直是个永恒的话题,编程中有一项也是可以提到效率的,那就是专注做一件事情,让其它没有强紧密联系的与之分开.这里分享下我们做CRUD时遇到的常见数据处理场景: 数据库表字段全部设计为非空,即使这 ...

  8. java之反射的基本介绍

    什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为Java的反射 ...

  9. 面试题思考:什么是 Java 的反射机制

    一.反射机制概述 Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法.这种在运行时动态的获取信息以及动态调用对象的方法 ...

随机推荐

  1. 网络协议之TLS

    前言 由于在TCP.UDP等方式传输数据时,数据包有可能被其他人截获,并解析出信息,这就给信息安全带来了很大的挑战.最初的SSL协议被网景公司提出,它不会影响上层协议(如HTTP.电子邮件等),但可以 ...

  2. JAVA学习(二) String使用equals方法和==分别比较的是什么?(转)

    String使用的equals方法和==的区别 equals方法和==的区别   首先大家知道,String既可以作为一个对象来使用,又可以作为一个基本类型来使用.这里指的作为一个基本类型来使用只是指 ...

  3. HBase0.99.2集群的搭建步骤(在hadoop2.6.4集群和zookeeper3.4.5集群上)

    HBase介绍(NoSql,不是关系型数据库) HBase是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBASE技术可在廉价PC Server上搭建起大规模结构化存储集群. HBase ...

  4. shiro xml标准配置

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  5. spring-boot集成Springfox-Swagger2

    import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Co ...

  6. linux学习笔记-8.vim

    ia/Ao/Or + ?替换 0:文件当前行的开头$:文件当前行的末尾G:文件的最后一行开头1 + G到第一行9 + G到第九行 = :9 dd:删除一行3dd:删除3行yy:复制一行3yy:复制3行 ...

  7. 【Ray Tracing in One Weekend 超详解】 光线追踪1-7 Dielectric 半径为负,实心球体镂空技巧

    今天讲这本书最后一种材质 Preface 水,玻璃和钻石等透明材料是电介质.当光线照射它们时,它会分裂成反射光线和折射(透射)光线. 处理方案:在反射或折射之间随机选择并且每次交互仅产生一条散射光线 ...

  8. html5解决ajax破坏浏览器机制

    pjax是一种基于ajax+history.pushState的新技术,该技术可以无刷新改变页面的内容,并且可以改变页面的URL.pjax是ajax+pushState的封装,同时支持本地存储.动画等 ...

  9. HDU3693 Math Teacher's Homework ---- 数位DP

    HDU3693 Math Teacher's Homework 一句话题意 给定$n, k以及m_1, m_2, m_3, ..., m_n$求$x_1 \oplus x_2 \oplus x_3 \ ...

  10. HDU.5730.Shell Necklace(分治FFT)

    题目链接 \(Description\) 有\(n\)个长度分别为\(1,2,\ldots,n\)的珠子串,每个有\(a_i\)种,每种个数不限.求有多少种方法组成长度为\(n\)的串.答案对\(31 ...