field.setAccessible(true) 簡介

今天查看別人寫的代碼時,發現這樣一句代碼,頓時來了興趣。java

須要注意setAccessible 並非在Field中的,而是在AccessibleObject中。安全

下面是AccessibleObject的解釋:app

意思是 AccessibleObject  類是 Field Method Constructor 類的基類。它提供反射對象繞過Java語言權限控制檢查的權限。ide

當Fields Methods Constructors被用來set get 對象域,調用方法或者產生初始化對象實例的時候會踐行權限檢查(public default(package) protected private)。工具

將反射對象中的 accessible 標誌位設置爲 true,就意味着容許客戶端擁有超級權限,好比Java對象序列化 或者 其餘持久化機制等一般禁止的機制。測試

因此咱們在accessible 標誌位設置爲true 的時候須要很是謹慎,這會帶來必定的安全隱患。this

**
 * 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);  方法的解釋。spa

意思就是改方式是用來設置獲取權限的。3d

若是 accessible 標誌被設置爲true,那麼反射對象在使用的時候,不會去檢查Java語言權限控制(private之類的);code

若是設置爲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
     */

 

下面舉例說明一下它的用處

一、首先新建一個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;
}

 

二、建立工具類,使用反射來進行對象的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);
            }
        }
    }


}

 

三、測試,首先註釋調下面這行代碼,而後在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)的用處是賦予反射對象超級權限,繞過語言權限檢查。

相關文章
相關標籤/搜索