反射機(jī)制:getDeclaredField和getField的區(qū)別說明
getDeclaredField和getField區(qū)別
在做后臺(tái)開發(fā)時(shí)實(shí)體的固定字段一般會(huì)抽取為一個(gè)父類,其他類繼承該父類,例如主鍵字段,會(huì)放到一個(gè)父類中(IdEntity),其他類繼承該類,但是我們在操作時(shí)操作的是子類,在通過子類獲取父類屬性是getDeclaredField和getField是不一樣的,簡單說
1、getDeclaredFiled 僅能獲取類本身的屬性成員(包括私有、共有、保護(hù))
2、getField 僅能獲取類(及其父類可以自己測試) public屬性成員
因此在獲取父類的私有屬性時(shí),要通過getSuperclass的之后再通過getDeclaredFiled獲取。
父類,出去id作為父類字段
import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.GenericGenerator; @MappedSuperclass public abstract class IdEntity { private String id; @Id @GeneratedValue(generator = "paymentableGenerator") @GenericGenerator(name = "paymentableGenerator", strategy = "uuid") @Column(name ="ID",nullable=false,length=32) public String getId() { return id; } public void setId(String id) { this.id = id; } }
子類
public class Reflect extends IdEntity { public String publicField; private String privateField; public Reflect(String publicField, String privateField) { super(); this.publicField = publicField; this.privateField = privateField; } public String getPrivateField() { return privateField; } public void setPrivateField(String privateField) { this.privateField = privateField; } }
測試類:
import java.lang.reflect.Field; public class ReflectDemo { /** * @Description: TODO * @param @param args * @return void * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws * @author ydecai * @date 2019-1-23 */ public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Reflect re = new Reflect("zhangsan", "lisi"); re.setId("111"); //getDeclaredFiled獲取本類屬性 // Field publicField = re.getClass().getDeclaredField("publicField"); // System.out.println(publicField.get(re)); Field publicField = re.getClass().getField("publicField"); System.out.println(publicField.get(re)); //getField獲取公有屬性,包括父類的,下面語句報(bào)錯(cuò) //Field privateField = re.getClass().getField("privateField"); Field privateField = re.getClass().getDeclaredField("privateField"); privateField.setAccessible(true); System.out.println(privateField.get(re)); //獲取父類私有屬性并獲取值 Field fileId = re.getClass().getSuperclass().getDeclaredField("id"); fileId.setAccessible(true); System.out.println(fileId.get(re)); } }
getDeclaredField方法與NoSuchFieldException異常
使用getDeclaredField()方法,發(fā)現(xiàn)有異常NoSuchFieldException,后續(xù)發(fā)現(xiàn)是因?yàn)閷?shí)體類使用了extends引起的,就百度了下原因。
發(fā)現(xiàn)getDeclaredField()方法只能獲取當(dāng)前類的所有屬性,但是不能獲取父類的屬性
這里引出兩個(gè)問題
第一個(gè)問題:getField()和getDeclaredField()方法是做什么的:
用Class的getField(String name)或getDelaredField(String name)是用來得到目標(biāo)類的指定屬性,返回類型是Field。
第二個(gè)問題:getField()和getDeclaredField()方法有什么區(qū)別:
getField(String name)只能獲取public的字段,包括父類的;
而getDeclaredField(String name)只能獲取自己聲明的各種字段,包括public,protected,private。
那么解決我遇到的問題有幾種方法:
方法1:棄用extends,但是我如果還想繼續(xù)使用extends怎么辦呢,看方法2。
方法2:可以通過getSuperclass()方法獲取父類,再調(diào)用getDeclaredField()方法。
Field field; try { field = obj.getClass().getDeclaredField(fieldName); } catch (NoSuchFieldException e) { //此處用于解決繼承導(dǎo)致的getDeclaredField不能直接獲取父類屬性的問題 field = obj.getClass().getSuperclass().getDeclaredField(fieldName); }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java對象轉(zhuǎn)化成String類型的四種方法小結(jié)
在java項(xiàng)目的實(shí)際開發(fā)和應(yīng)用中,常常需要用到將對象轉(zhuǎn)為String這一基本功能。本文就詳細(xì)的介紹幾種方法,感興趣的可以了解一下2021-08-08Java實(shí)現(xiàn)圖片上文字內(nèi)容的動(dòng)態(tài)修改的操作步驟
在數(shù)字圖像處理領(lǐng)域,Java提供了強(qiáng)大的庫來處理圖片,包括讀取、修改和寫入圖片,如果你需要在Java應(yīng)用程序中修改圖片上的文字內(nèi)容,可以通過圖像處理技術(shù)來實(shí)現(xiàn),這篇博文將介紹如何使用Java實(shí)現(xiàn)圖片上文字內(nèi)容的動(dòng)態(tài)修改,需要的朋友可以參考下2024-07-07spring boot使用thymeleaf為模板的基本步驟介紹
Spring Boot項(xiàng)目的默認(rèn)模板引擎是Thymeleaf,這沒什么好說的,個(gè)人覺得也非常好,下面這篇文章主要給大家介紹了關(guān)于spring boot使用thymeleaf為模板的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01JAVA HashSet和TreeSet 保證存入元素不會(huì)重復(fù)的操作
這篇文章主要介紹了JAVA HashSet和TreeSet 保證存入元素不會(huì)重復(fù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09idea創(chuàng)建包含多個(gè)springboot module的maven project的方法
這篇文章主要介紹了idea創(chuàng)建包含多個(gè)springboot module的maven project的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09