今天查看別人寫的代碼時,發現這樣一句代碼,頓時來了興趣。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)的用處是賦予反射對象超級權限,繞過語言權限檢查。