java內省機制 + 內省是什么 + 內省實現方式 + 和反射的區別

?

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

一、內省是什么、實現方式:

內省(Introspector)是Java語言對Bean類屬性、事件的一種缺省處理方法。
例如類A中有屬性name,那我們可以通過getName,setName來得到其值或者設置新的值。
通過getName/setName來訪問name屬性,這就是默認的規則。
Java中提供了一套API用來訪問某個屬性的getter/setter方法,通過這些API可以使你不需要了解這個規則,
這些API存放于包java.beans中。Java語言對Bean類屬性、事件的一種缺省處理方法。例如類A中有屬性name,那我們可以通過getName,setName來得到其值或者設置新的值。通過getName/setName來訪問name屬性,這就是默認的規則。Java中提供了一套API用來訪問某個屬性的getter/setter方法,通過這些API可以使你不需要了解這個規則(但你最好還是要搞清楚),這些API存放于包java.beans中。一般的做法是通過類Introspector來獲取某個對象的BeanInfo信息,
然后通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),
通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,
然后我們就可以通過反射機制來調用這些方法。一般的做法是通過類Introspector來獲取某個對象的BeanInfo信息,然后通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然后我們就可以通過反射機制來調用這些方法。

內省的解釋

內省在wiki上的解釋:

在計算機科學中,內省是指計算機程序在運行時(Run time)檢查對象(Object)類型的一種能力,通常也可以稱作運行時類型檢查。?
不應該將內省和反射混淆。相對于內省,反射更進一步,是指計算機程序在運行時(Run time)可以訪問、檢測和修改它本身狀態或行為的一種能力。

二、內省和反射區別:區別:

反射式在運行狀態把Java類中的各種成分映射成相應的Java類,可以動態的獲取所有的屬性以及動態調用任意一個方法,強調的是運行狀態。?
內省機制是通過反射來實現的,BeanInfo用來暴露一個bean的屬性、方法和事件,以后我們就可以操縱該JavaBean的屬性


這里寫圖片描述
在Java內省中,用到的基本上就是上述幾個類。?
通過BeanInfo這個類就可以獲取到類中的方法和屬性,具體的可以參考JDK文檔

Web 開發框架 Struts 中的 FormBean 就是通過內省機制來將表單中的數據映射到類的屬性上,
因此要求 FormBean 的每個屬性要有 getter/setter 方法。
但也并不總是這樣,什么意思呢?就是說對一個 Bean 類來講,
我可以沒有屬性,但是只要有 getter/setter 方法中的其中一個,
那么 Java 的內省機制就會認為存在一個屬性,比如類中有方法 setMobile ,
那么就認為存在一個 mobile 的屬性。
將 Java 的反射以及內省應用到程序設計中去可以大大的提供程序的智能化和可擴展性。
有很多項目都是采取這兩種技術來實現其核心功能,例如我們前面提到的 Struts ,
還有用于處理 XML 文件的 Digester 項目,其實應該說幾乎所有的項目都或多或少的采用這兩種技術。
在實際應用過程中二者要相互結合方能發揮真正的智能化以及高度可擴展性。 

三、內省代碼演示:

1).內省(Introspector)是Java?語言對Bean類屬性、事件的一種缺省處理方法。例如類 A 中有屬性 name, 那我們可以通過 getName,setName 來得到其值或者設置新的值。通過 getName/setName 來訪問 name 屬性,這就是默認的規則。?

?? Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,通過這些 API 可以使你不需要了解這個規則(但你最好還是要搞清楚),這些 API 存放于包 java.beans 中。

2).直接通過屬性的描述器java.beans.PropertyDescriptor類,來訪問屬性的getter/setter 方法;

相關代碼:

public?class?Point?{?????private?Integer?x;?????private?Integer?y;?????public?Point(Integer?x,?Integer?y)?{?????super();?????this.x?=?x;?????this.y?=?y;?????}?????public?Integer?getX()?{?????return?x;?????}????????public?void?setX(Integer?x)?{?????this.x?=?x;?????}?????public?Integer?getY()?{?????return?y;?????}??????public?void?setY(Integer?y)?{?????this.y?=?y;?????}?????}?????import?java.beans.PropertyDescriptor;?????import?java.lang.reflect.Method;?????public?class?Reflect?{?????public?static?void?main(String[]?args)?throws?Exception?{?????Point?point?=?new?Point(2,?5);?????String?proName?=?"x";?????getProperty(point,?proName);?????setProperty(point,?proName);?????}?????private?static?void?setProperty(Point?point,?String?proName)?throws?Exception?{?????PropertyDescriptor?proDescriptor?=?new?PropertyDescriptor(proName,?Point.class);?????Method?methodSetX?=?proDescriptor.getWriteMethod();?????methodSetX.invoke(point,?8);?????System.out.println(point.getX());//?8?????}?????private?static?void?getProperty(Point?point,?String?proName)?throws?Exception?{?????PropertyDescriptor?proDescriptor?=?new?PropertyDescriptor(proName,?Point.class);?????Method?methodGetX?=?proDescriptor.getReadMethod();?????Object?objx?=?methodGetX.invoke(point);?????System.out.println(objx);//?2?????}?????}??????

3).通過類 Introspector 來獲取某個對象的 BeanInfo 信息,然后通過 BeanInfo 來獲取屬性的描述器( PropertyDescriptor ),通過這個屬性描述器就可以獲取某個屬性對應的 getter/setter 方法,然后我們就可以通過反射機制來調用這些方法。

相關代碼:
把2中的getProperty()修改成如下形式:

private?static?void?getProperty(Point?point,?String?proName)?throws?Exception?{?????BeanInfo?beanInfo?=?Introspector.getBeanInfo(point.getClass());?????PropertyDescriptor[]?proDescriptors?=?beanInfo.getPropertyDescriptors();?????for(PropertyDescriptor?prop:?proDescriptors){?????if(prop.getName().equals(proName)){?????Method?methodGetx?=?prop.getReadMethod();?????System.out.println(methodGetx.invoke(point));//8?????break;?????}?????}?????}???

4).我們又通常把javabean的實例對象稱之為值對象 (Value Object),因為這些bean中通常只有一些信息字段和存儲方法,沒有功能性方法。一個JavaBean類可以不當JavaBean用,而當成普通類 用。JavaBean實際就是一種規范,當一個類滿足這個規范,這個類就能被其它特定的類調用。一個類被當作javaBean使用時,JavaBean的 屬性是根據方法名推斷出來的,它根本看不到java類內部的成員變量(javabean的成員變量通常都是私有private的)。

5).除了反射用到的類需要引入外,內省需要引入的類如下所示,它們都屬于java.beans包中的類,自己寫程序的時候也不能忘了引入相應的包或者類。

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

6).下面講解一些開源的工具類Beanutils,需要額外下載的,commons-beanutils.jar,要使用它還必須導入commons-logging.jar包,不然會出異常;
相關代碼一:

public?static?void?main(String[]?args)?throws?Exception?{?????Point?point?=?new?Point(2,?5);?????String?proName?=?"x";?????BeanUtils.setProperty(point,?proName,?"8");?????System.out.println(point.getX());//?8?????System.out.println(BeanUtils.getProperty(point,?proName));//?8?????System.out.println(BeanUtils.getProperty(point,?proName).getClass().getName());//?java.lang.String?????BeanUtils.setProperty(point,?proName,?8);?????System.out.println(BeanUtils.getProperty(point,?proName).getClass().getName());//?java.lang.String?????}?????//我們看到雖然屬性x的類型是Integer,但是我們設置的時候無論是Integer還是String,BeanUtils的內部都是當成String來處理的。??

相關代碼二:
BeanUtils支持javabean屬性的級聯操作;

public?static?void?main(String[]?args)?throws?Exception?{?????Point?point?=?new?Point(2,?5);//在point中加一個屬性?private?Date?birth?=?new?Date();并產生setter/getter方法?????String?proName?=?"birth";?????Date?date=?new?Date();?????date.setTime(10000);?????BeanUtils.setProperty(point,?proName,?date);?????System.out.println(BeanUtils.getProperty(point,?proName));?????BeanUtils.setProperty(point,?"birth.time",?10000);?????System.out.println(BeanUtils.getProperty(point,?"birth.time"));//10000?????
}?????
//之所以可以?BeanUtils.setProperty(point,?"birth.time",?10000);這樣寫,那是因為Date類中有getTime()和setTime()方法,即Date類中相當于有time這個屬性。???

相關代碼三:
BeanUtils和PropertyUtils對比:

public?static?void?main(String[]?args)?throws?Exception?{?????Point?point?=?new?Point(2,?5);?????String?proName?=?"x";?????BeanUtils.setProperty(point,?proName,?"8");?????System.out.println(BeanUtils.getProperty(point,?proName));//8?????System.out.println(BeanUtils.getProperty(point,?proName).getClass().getName());//java.lang.String?????//?PropertyUtils.setProperty(point,?proName,?"8");//exception:argument?type?mismatch?????PropertyUtils.setProperty(point,?proName,?8);?????System.out.println(PropertyUtils.getProperty(point,?proName));//8?????System.out.println(PropertyUtils.getProperty(point,?proName).getClass().getName());//java.lang.Integer?????
}?????
//BeanUtils它以字符串的形式對javabean進行轉換,而PropertyUtils是以原本的類型對javabean進行操作。如果類型不對,就會有argument?type?mismatch異常。??

6).理解了相應的原理,那些現成的工具用起來就會更舒服,如Beanutils與 PropertyUtils工具。這兩個工具設置屬性的時候一個主要區別是PropertyUtils.getPropety方法獲得的屬性值的類型為該 屬性本來的類型,而BeanUtils.getProperty則是將該屬性的值轉換成字符串后才返回

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451171.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

百度聯合長虹發布第二款云手機 售價900元以下

摘要:【搜狐IT消息】5月15日消息,百度今天宣布聯合長虹發布第二款智能手機,采用3.5英寸屏幕、300萬像素攝像頭,650MHz主頻處理器,零售價格在700-899元之間,中國聯通將為其提供話費補貼。 【搜狐IT消息】5月…

vmware workstation17環境安裝centos7

打開控制面板,搜索“服務”,啟動vmware authorize service -------解決無法開啟虛擬機問題之無法連接MKS 2.虛擬機硬盤擴展為15G------解決安裝centos7時出現的“檢查存儲配置出錯”問題 3.硬盤分區----/boot 300mb(不能小于200mb&#xff0…

博客園中的源代碼格式顯示

昨天寫了一篇文章,但是在寫的時候呢,沒有注意,直接將代碼復制上去了,今天正好有人提醒,看到了格式的混亂,借此記錄整理一下,如何能直接粘貼代碼,而且格式(縮進&#xff0…

static的使用

類中的靜態變量在程序運行期間,其內存空間對所有該類的對象實例而言是共享的,為了節省系統內存開銷、共享資源,應該對一些適合使用static的變量聲明為靜態變量。 變量聲明為static的使用場景: (1)變量所…

Linux內核的裁剪和移植

linux內核的裁剪和移植具體都在這個網址里面。https://blog.csdn.net/xie0812/article/details/10816059https://blog.csdn.net/xie0812/article/details/10821779轉載于:https://blog.51cto.com/13401435/2145947

李開復唱衰互聯網手機:大部分公司會失敗

摘要:互聯網企業和手機制造企業之間巨大的鴻溝也被李開復鮮明地指出來:“兩個產業差別巨大,企業基因不同。”百度此前也坦誠表示,與長虹合作的千元機,主要是針對2000元以下的用戶體驗,不能與四五千元的蘋果…

【POJ】3268 Silver Cow Party

題目鏈接:http://poj.org/problem?id3268 題意 :有N頭奶牛,M條單向路。X奶牛開party,其他奶牛要去它那里。每頭奶牛去完X那里還要返回。去回都是走的最短路。現在問這里面哪頭奶牛走的路最長。 題解:對每個奶牛i與X做…

java.util.ConcurrentModificationException異常分析

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 Java在操作ArrayList、HashMap、TreeMap等容器類時,遇到了java.util.ConcurrentModificationException異常。以ArrayList為例…

redis基本數據類型之String

redis基本數據類型之String redis一共分為5中基本數據類型:String,Hash,List,Set,ZSet String String類型是包含很多種類型的特殊類型,并且是二進制安全的。比如序列化的對象進行儲存,比如一張圖片進行二進制儲存,比如一個簡單…

Laravel5.5之事件監聽、任務調度、隊列

一、事件監聽 流程: 1.1 創建event php artisan make:event UserLogin LoginController.php /*** The user has been authenticated.** param \Illuminate\Http\Request $request* param mixed $user* return mixed*/protected function authenticated(Request …

朱江洪功成身退 朱董配解體誰主格力(圖)

摘要:中國家電營銷委員會副理事長洪仕斌向時代周報記者表示:“朱江洪和董明珠已經完成了他們在格力發展前二十年的使命。“朱董配”解體之后,有人質疑格力“技術營銷”的格局必將被打破,難以延續,“董氏班底”與朱江洪…

一些dos下簡單命令

(1)切換盤符 d: 回車 (2)顯示某目錄下的所有文件或者文件夾(掌握) dir 回車 (3)創建文件夾 md 文件夾名稱 回車 (4)刪除文件夾 rd 文件夾名稱 回車 (5)進入目錄(掌握) 單級進入 cd 目錄名稱 多級進入 cd 目錄名稱1\目錄名稱2\... (6)回退目錄(掌握) 單級回退 cd.. …

ssh服務器拒絕了密碼 請再試一次 Xftp5連接失敗

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 我的情況都很簡單: 第一回主機 ip 不對, 第二次 是賬號、密碼都不對。 最后 IP、賬號、密碼都對了 就連上了。

后端DTO(數據傳輸對象)與DAO(數據庫數據源對象)解耦的好處

我們在后端的開發中經常會將DO對象傳到Service層直接作為DTO傳給前端,這樣做其實會有很多弊端。 (一)DO對象一般其成員域和數據庫字段是對應的,所以不能添加額外的字段,但是有時候端就是需要這個字段。反之前端要向后…

【刷算法】字符串的全排列

題目描述 輸入一個字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。 分析 沒啥好分析的了,這個題不會,上網查的思路,大概就是: abc分化…

BZOJ.2741.[FOTILE模擬賽]L(分塊 可持久化Trie)

題目鏈接 首先記\(sum\)為前綴異或和,那么區間\(s[l,r]sum[l-1]^{\wedge}sum[r]\)。即一個區間異或和可以轉為求兩個數的異或和。 那么對\([l,r]\)的詢問即求\([l-1,r]\)中某兩個數異或的最大值。 區間中某一個數和已知的一個數異或的最大值可以用可持久化Trie \(O(…

傳騰訊人事大地震 馬化騰將重整公司架構

摘要:5月17日消息,傳騰訊董事長馬化騰將重新組織公司架構,為騰訊大換血。據悉,騰訊之所以選擇互動娛樂部門負責人接任這一重要崗位,也是因為互娛部門業績持續快速發展,成為了“騰訊帝國”發展的核心驅動力之…

阿里云對象存儲OSS與文件存儲NAS的區別

一、簡介 應用場景:選擇一款存儲產品,面向文檔數據的存取,不會涉及到數據處理。 產品選型主要從OSS和NAS中選擇一款,滿足文檔存儲的需求。 二、NAS優缺點 NAS 是一種采用直接與網絡介質相連的特殊設備實現數據存儲的機制。由于這些…

Thread.yield()

&#xff08;一&#xff09;java yield()方法注釋&#xff1a; /*** A hint to the scheduler that the current thread is willing to yield* its current use of a processor. The scheduler is free to ignore this* hint.** <p> Yield is a heuristic attempt to im…

WSDL 詳解

轉載自&#xff1a;http://kalogen.javaeye.com/blog/418958 WSDL (Web Services Description Language,Web服務描述語言)是一種XML Application&#xff0c;他將Web服務描述定義為一組服務訪問點&#xff0c;客戶端可以通過這些服務訪問點對包含面向文檔信息或面向過程調用的服…