zoukankan      html  css  js  c++  java
  • field.setAccessible(true) 简介

    今天查看别人写的代码时,发现这样一句代码,顿时来了兴趣。

    需要注意setAccessible 并不是在Field中的,而是在AccessibleObject中。

    下面是AccessibleObject的解释:

    意思是 AccessibleObject  类是 Field Method Constructor 类的基类。它提供反射对象绕过Java语言权限控制检查的权限。

    当Fields Methods Constructors被用来set get 对象域,调用方法或者产生初始化对象实例的时候会践行权限检查(public default(package) protected private)。

    将反射对象中的 accessible 标志位设置为 true,就意味着允许客户端拥有超级权限,比如Java对象序列化 或者 其他持久化机制等通常禁止的机制。

    所以我们在accessible 标志位设置为true 的时候需要非常谨慎,这会带来一定的安全隐患。

    **
     * The AccessibleObject class is the base class for Field, Method and
     * Constructor objects.  It provides the ability to flag a reflected
     * object as suppressing default Java language access control checks
     * when it is used.  The access checks--for public, default (package)
     * access, protected, and private members--are performed when Fields,
     * Methods or Constructors are used to set or get fields, to invoke
     * methods, or to create and initialize new instances of classes,
     * respectively.
     *
     * <p>Setting the {@code accessible} flag in a reflected object
     * permits sophisticated applications with sufficient privilege, such
     * as Java Object Serialization or other persistence mechanisms, to
     * manipulate objects in a manner that would normally be prohibited.
     *
     * <p>By default, a reflected object is <em>not</em> accessible.
     *
     * @see Field
     * @see Method
     * @see Constructor
     * @see ReflectPermission
     *
     * @since 1.2
     */

    下面是 field.setAccessible(true);  方法的解释。

    意思就是改方式是用来设置获取权限的。

    如果 accessible 标志被设置为true,那么反射对象在使用的时候,不会去检查Java语言权限控制(private之类的);

    如果设置为false,反射对象在使用的时候,会检查Java语言权限控制。

    需要注意的是,设置为true会引起安全隐患。

        /**
         * Set the {@code accessible} flag for this object to
         * the indicated boolean value.  A value of {@code true} indicates that
         * the reflected object should suppress Java language access
         * checking when it is used.  A value of {@code false} indicates
         * that the reflected object should enforce Java language access checks.
         *
         * <p>First, if there is a security manager, its
         * {@code checkPermission} method is called with a
         * {@code ReflectPermission("suppressAccessChecks")} permission.
         *
         * <p>A {@code SecurityException} is raised if {@code flag} is
         * {@code true} but accessibility of this object may not be changed
         * (for example, if this element object is a {@link Constructor} object for
         * the class {@link java.lang.Class}).
         *
         * <p>A {@code SecurityException} is raised if this object is a {@link
         * java.lang.reflect.Constructor} object for the class
         * {@code java.lang.Class}, and {@code flag} is true.
         *
         * @param flag the new value for the {@code accessible} flag
         * @throws SecurityException if the request is denied.
         * @see SecurityManager#checkPermission
         * @see java.lang.RuntimePermission
         */

    下面举例说明一下它的用处

    1、首先新建一个bean类---Book

    public class Book {
        public String getBookId() {
            return bookId;
        }
    
        public void setBookId(String bookId) {
            this.bookId = bookId;
        }
    
        public String getBookName() {
            return BookName;
        }
    
        public void setBookName(String bookName) {
            BookName = bookName;
        }
    
        private String bookId;
        private String BookName;
    }

    2、创建工具类,使用反射来进行对象的set操作。

    public class ReflectUtil {
    
        private static Field getField(Object obj, String fieldName)
        {
            Field field = null;
            for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass())
            {
                try
                {
                    field = clazz.getDeclaredField(fieldName);
                    break;
                }
                catch (NoSuchFieldException e)
                {
                    System.out.println("catch NoSuchFieldException.");
                    //这里不用做处理,子类没有该字段可能对应的父类有,都没有就返回null。
                }
            }
            return field;
        }
    
    
        /**
         * 利用反射设置指定对象的指定属性为指定的值.
         *
         * @param obj 目标对象
         * @param fieldName 目标属性
         * @param fieldValue 目标值
         */
        public static void setFieldValue(Object obj, String fieldName, String fieldValue)
        {
            Field field = ReflectUtil.getField(obj, fieldName);
            if (field != null)
            {
                try
                {
                    field.setAccessible(true);
                    field.set(obj, fieldValue);
                    System.out.println("success!");
                }
                catch (IllegalArgumentException e)
                {
                    System.out.println("++++++setFieldValue IllegalArgumentException:::+++++++" + e);
                }
                catch (IllegalAccessException e)
                {
                    System.out.println("++++++setFieldValue IllegalAccessException:::+++++++" + e);
                }
            }
        }
    
    
    }

    3、测试,首先注释调下面这行代码,然后在main方法中调用反射工具类进行变量set。

    field.setAccessible(true);
    public class Test3 {
    
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException {
            Book book = new Book();
            ReflectUtil.setFieldValue(book,"bookId","1");
        }
    
    }

    下面是结果,报错,表示不能对private域进行操作。

     我们将注释取消,再运行一下,发现成功了。

     

    这就证明了field.setAccessible(true)的用处是赋予反射对象超级权限,绕过语言权限检查。

  • 相关阅读:
    iOS-深入理解(转载)
    iOS开发
    夜光遥感
    希尔伯特曲线在地图图像分割中的应用
    希尔伯特曲线
    NLP生成论文
    MapGIS SDK(C++)【基础篇】
    从npm到vue和nodejs
    分形在遥感和GIS中的应用
    MapReduce、Hadoop、PostgreSQL、Spark
  • 原文地址:https://www.cnblogs.com/cuglkb/p/8463039.html
Copyright © 2011-2022 走看看