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)的用處是賦予反射對象超級權限,繞過語言權限檢查。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM