1. 程式人生 > >Java 中AccessibleObject那些事兒

Java 中AccessibleObject那些事兒

       以前我很少寫東西,感覺自己知道就可以了嘛,最近我改變了我的看法,把某些東西寫出來可以讓我們梳理一些對它的理解,更甚至有時候你會發現你看問題的盲點!

好了,進入正題,今天研究了一段程式碼,就是如何改變final型別的值。大家知道final型別的值一般情況下是不能改變的,但是經過樓主的不斷嘗試。發現它也是可以改變的。

這裡我是用了AccessibleObject  ,在進行詳細講解之前,先來說一說AccessibleObject的相關知識。

public class AccessibleObject extends Object implements AnnotatedElement


AccessibleObject 類實現了AnnotatedElement,它是 Field、Method 和 Constructor 物件的基類。它提供了將反射的物件標記為在使用時取消預設 Java 語言訪問控制檢查的能力。對於公共成員、預設(打包)訪問成員、受保護成員和私有成員,在分別使用 Field、Method 或 Constructor 物件來設定或獲得欄位、呼叫方法,或者建立和初始化類的新例項的時候,會執行訪問檢查。

AccessibleObject:的方法:

isAccessible:

public boolean isAccessible()獲得此物件的 accessible 標誌的值。

此物件的返回值 就是accessible的標誌值,一般情況下無論 public,private,protected,預設等修飾的屬性的access值均為false(注意他的意思並非是訪問許可權而是對該自己執行安全檢查)。 setAccessible: public static void setAccessible(object  , boolean flag) 
throws SecurityException使用單一安全性檢查(為了提高效率)為一物件設定 accessible 標誌。如果存在安全管理器,則在 ReflectPermission("suppressAccessChecks") 許可權下呼叫 checkPermission 方法。當flag 為 true,表示不開啟安全檢查,但是不能更改輸入 object的任何元素的可訪問性(例如,如果元素物件是 Class 類的 Constructor 物件),則會引發 SecurityException。如果發生 SecurityException,對於少於(不包括)發生異常的元素的陣列元素,可以將物件的可訪問性設定為 flag;對於超出(包括)引發異常的元素的那些元素,則不更改其可訪問性.

getAnnotation

  public <T extends Annotation> T getAnnotation(Class<T> annotationClass)從介面 AnnotatedElement 複製的描述 .如果存在該元素的指定型別的註釋,則返回這些註釋,否則返回 null。  指定者:介面 AnnotatedElement 中的 getAnnotation    引數: annotationClass - 對應於註釋型別的 Class 物件    返回:如果該元素的指定註釋型別的註釋存在於此物件上,則返回這些註釋,否則返回 null

isAnnotationPresent

  public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 從介面 AnnotatedElement 複製的描述 ,如果指定型別的註釋存在於此元素上,則返回 true,否則返回 false。此方法主要是為了便於訪問標記註釋而設計的。 指定者:介面 AnnotatedElement 中的 isAnnotationPresent    引數:annotationClass - 對應於註釋型別的 Class 物件    返回:如果指定註釋型別的註釋存在於此物件上,則返回 true,否則返回 false

getAnnotation

  public Annotation[] getAnnotations()從介面 AnnotatedElement 複製的描述 ,返回此元素上存在的所有註釋。(如果此元素沒有註釋,則返回長度為零的陣列。)該方法的呼叫方可以隨意修改返回的陣列;這不會對其他呼叫方返回的陣列產生任何影響。   指定者:介面 AnnotatedElement 中的 getAnnotations    返回: 此元素上存在的所有註釋

getDeclaredAnnotation

  public Annotation[] getDeclaredAnnotations()從介面 AnnotatedElement 複製的描述   返回直接存在於此元素上的所有註釋。與此介面中的其他方法不同,該方法將忽略繼承的註釋。(如果沒有註釋直接存在於此元素上,則返回長度為零的一個數組。)該方法的呼叫方可以隨意修改返回的陣列;這不會對其他呼叫方返回的陣列產生任何影響。    指定者: 介面 AnnotatedElement 中的 getDeclaredAnnotations    返回: 直接存在於此元素上的所有註釋
我建立了一個Student的model: public class Student {
 private  String name;
 private String no;
 public String nickname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
首先:public class Reflect {
public static void main(String[] args) {
Student stu=new Student();
stu.setName("gzq");
stu.setNickname("jiu ge");
stu.setNo("100901016");
    Field field=stu.getClass().getDeclaredField("name");
   Field field1=stu.getClass().getField("name");
                field.isAccessible();
field.setAccessible(true);
field.set(stu, "九哥");
System.out.println("field.get(stu):"+field.get(stu));
這樣打印出的結果:java.lang.NoSuchFieldException: name
at java.lang.Class.getField(Class.java:1537)
at field.Reflect.main(Reflect.java:15
原因是

getField不能訪問private修飾的屬性。

將其改為:

Field field=stu.getClass().getDeclaredField("name");
Field field1=stu.getClass().getField("nickname");

正常操作:打印出的結果是:九哥,而不是jiuge,這說明值確實變了。

如果不放心,可以在加一段程式碼:

public class Reflect {
public static void main(String[] args) {
Student stu=new Student();

stu.setName("gzq");
stu.setNickname("jiu ge");
stu.setNo("100901016");
try {
Field field=stu.getClass().getDeclaredField("name");
Field field1=stu.getClass().getField("nickname");//getfield 只能獲取public欄位
System.out.println("field:"+field);
System.out.println("field1:"+field1);
System.out.println("field.isAccessible:"+field.isAccessible());
field.isAccessible();
field.setAccessible(true);
field.set(stu, "九哥");
System.out.println("field.get(stu):"+field.get(stu));
System.out.println(stu.getName());
 
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

通過加了屬性的getName方法看一看:列印結果:

field:private java.lang.String field.Student.name
field1:public java.lang.String field.Student.nickname
field.isAccessible:false
field.get(stu):九哥
stu.getName():九哥

getName()獲得的值確實是修改後的值

總結;仔細想了一下,其實這裡的name是string 型別的,我看了一下string的原始碼,發現string的value 是final型別

一般final型別是沒辦法修改的,但是通過這種方法可以進行修改的。

相關推薦

Java AccessibleObject那些事兒

       以前我很少寫東西,感覺自己知道就可以了嘛,最近我改變了我的看法,把某些東西寫出來可以讓我們梳理一些對它的理解,更甚至有時候你會發現你看問題的盲點! 好了,進入正題,今天研究了一段程式碼,

ASP.NET Core HTTP 管道那些事兒

那些事兒 管道 IApplicationBuilderIApplicationBuilder 是應用大家最熟悉它的地方應該就是位於 Startup.cs 文件中的 Configure 方法了吧public void Configure(IApplicationBuilder app, ILoggerF

【經驗分享】響應式網站項目實操過程那些事兒

oat fib lin style 定義 oss 柵格 簡單 報名 本次網站改版升級是我來到新公司的第一個項目,需求之初並沒有提及要做響應式,在首次評審時領導和研發均認為響應式處理與我們網站相對契合,就這樣我開始了我職場生涯中第一個響應式網站設計。下面就跟大家分享響應式網站

網路那些事兒(一)之神奇的通訊

       考試大戰在即,這是大二生涯中最後一場戰役,為了給自己這半年的戎馬生涯畫上一個圓滿句號,故最近幾天在複習(其實說預習更為合理一些)《計算機網路》這門課程。臨時抱佛腳,真心地不好。不過好在自

說說java棧溢位那些事兒

今天寫了一個bug導致出現了棧溢位,出現棧溢位的根本原因是出現了無限次的遞迴,遞迴巢狀的層次太多,方法進棧次數太多,導致棧區不足出現StackOverFlow,寫程式碼以來第一次出現這種bug,幸虧自己之前對這方面有了解,解決的還算及時,同時這個bug也讓我體會到,寫程式碼真

java那些坑(一)

下面的坑有些來自別人的技術部落格,有些事以前自己遇到的坑,持續補充。。。 坑1:三目運算子 首先我們看一下這道題:char x = 'x';System.out.println(true?120:x); 我們的第一反應結果不就是120嗎,但是我們實際執行一下,結果是x。是

java那些關鍵字?

關鍵字是Java程式中具有特殊含義的字元,不能當作識別符號使用。Java語言在其發展的過程中關鍵字越來越多,甚至有些關鍵字的出現影響到了原來的Java程式,例如,關鍵字enum出現後,以前如果某個程式原始檔用enum作為變數,將會發生編譯錯誤。甚至有一些開源的工

談談 Java 那些“瑣”事

# 一、公平鎖&非公平鎖 ## 是什麼 - 公平鎖:執行緒按照申請鎖的順序來獲取鎖;在併發環境中,每個執行緒都會被加到等待佇列中,按照 FIFO 的順序獲取鎖。 ![](https://gitee.com/songjilong/FigureBed/raw/master/img/20200921102

Java那些關於String和字串常量池你不得不知道的東西

## 老套的筆試題 在一些老套的筆試題中,會要你判斷s1==s2為false還是true,s1.equals(s2)為false還是true。 ```java String s1 = new String("xyz"); String s2 = "xyz"; System.out.println(s1 =

java方法重寫和過載的那些事兒

1.重寫和過載分別是什麼意思 重寫(Override): 重寫是子類重新定義了父類的同名同參方法,覆蓋了父類的方法,因此,我們也把這種方式叫做“覆寫”。 過載(Overload): 過載是同一個類中,宣告的方法名字相同,但是引數不同的個方法,通過呼叫時傳不同的引數來達到呼叫名

關於<Java RMI、JNDI、LDAP、JRMP、JMX、JMS那些事兒(上)>看後的一些總結-1

原文地址:https://www.anquanke.com/post/id/194384#h3-3 1.java rmi 關於rmi客戶端和服務端通訊的過程,java的方法都實現在rmi服務端,客戶端實際上是通過訪問rmi登錄檔拿到stub,然後再通過它呼叫服務端方法,那麼呼叫方法時要傳遞引數,引數可以為一般

關於<Java RMI、JNDI、LDAP、JRMP、JMX、JMS那些事兒(上)>看後的一些總結-2

關於JNDI: 命名系統是一組關聯的上下文,而上下文是包含零個或多個繫結的物件,每個繫結都有一個原子名(實際上就是給繫結的物件起個名字,方便查詢該繫結的物件), 使用JNDI的好處就是配置統一的管理介面,下層可以使用RMI、LDAP或者CORBA來訪問目標服務 要獲取初始上下文,需要使用初始上下文工

html頁面拍照和上傳照片那些事兒(二)

read itl 加載完成 大小 上傳照片 那些事 cnblogs 設置 新建 本文為原創,轉載請註明出處: cnzt 文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6895352.html 本文主要說下iOS上

說說Java生態圈的那些事兒

tro 學會 登錄 內存 bar 傳遞 成對出現 描述 first 文章目錄: 1.生態圈概述。 2.說說Java,高級Java,Java生態圈的衍生 3. 說說servlet、servlet容器、比較tomcat、jetty、tomcat、jboss; 1. 哪個項目

漫談Java IO之 NIO那些事兒

rand pub 一個 soc 簡單的 eap blog 分享 test 前面一篇中已經介紹了基本IO的使用以及最簡單的阻塞服務器的例子,本篇就來介紹下NIO的相關內容,前面的分享可以參考目錄: 網絡IO的基本知識與概念 普通IO以及BIO服務器 NIO的使用與服務器

C# Thread,Task,Async/Await,IAsyncResult 的那些事兒

tostring source spa turn urn 每次 star 是否 main函數 說起異步,Thread,Task,async/await,IAsyncResult 這些東西肯定是繞不開的,今天就來依次聊聊他們 1.線程(Thread) 多線程的意義在於一個應用

袋鼠雲數據臺專欄(六):企業數據指標的那些事兒

span 帶來 什麽 如何解決 煙囪 color system data 混亂 本文作者:子璽袋鼠雲數據中臺解決方案專家。擁有近10年大數據從業經驗,擁有PMP項目管理資格認證,精通數據類項目的開發實施和管理。曾服務過國家工商總局、北京市工商局、北京市財政局、廣州開發區大數

http請求content-type的那些事兒

在jquery+ajax盛行的年代裡,前後端互動實在太方便了,ajax發起一個請求就是這麼簡單 $.ajax({ url:'', type:'post', data:{},//引數 ... }) 久而久之,裡面很多的細節都被我們忽略了,等到有一天,沒有jque

前臺往後臺傳送JSON物件以及去json的鍵值的那些事兒····

首先,定義一個JSON物件 var data = {name:‘wwww’} (1)往後臺傳送之前需要將JSON物件序列化成一個JSON字串;使用JSON.stringify(data), (2)隨後在後臺需要將傳過來的JSON字串轉換成JSON物件,不然無法取值(這是我的理解),使用.pa

《SVM筆記系列之六》支援向量機的核技巧那些事兒

《SVM筆記系列之六》支援向量機中的核技巧那些事兒 前言 我們在前文[1-5]中介紹了線性支援向量機的原理和推導,涉及到了軟和硬的線性支援向量機,還有相關的廣義拉格朗日乘數法和KKT條件等。然而,光靠著前面介紹的這些內容,只能夠對近似於線性可分的資料進行分割,而不能對非線性的資料