解決lombok的@Data注解無法打印繼承的父類信息問題
問題場景
子類StudentResp繼承父類PersonResp,子類也擁有了父類的屬性。
給子類中繼承的父類屬性的賦值,但是打印了以后只會顯示子類信息,父類信息不顯示。
- 子類:學(xué)生類繼承父類人員類
@Data public class StudentResp extends PersonResp { /** * 學(xué)號 */ private Integer studentId; /** * 成績 */ private Integer score; }
- 父類:人員類
@Data public class PersonResp { /** * 姓名 */ private String name; /** * 年齡 */ private Integer age; }
代碼中給子類以及繼承的父類信息賦值然后打印
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學(xué)生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風(fēng)清揚(yáng)"); studentResp.setAge(18); //打印學(xué)生子類信息 System.out.println(studentResp); }
打印出來只有子類自己的屬性,父類的屬性沒有出來
問題分析
單獨(dú)獲取子類中父類的信息(name跟age),觀察打印看有沒有值
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學(xué)生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風(fēng)清揚(yáng)"); studentResp.setAge(18); //打印父類信息 System.out.println("姓名:" + studentResp.getName()); System.out.println("年齡:" + studentResp.getAge()); }
打印出來發(fā)現(xiàn)是有值的
確認(rèn)了繼承本身是沒有問題的,繼承的父類的值都可以給上,也能獲取到,隨后直接打開target對應(yīng)目錄下的StudentResp子類,觀察編譯后的代碼
public class StudentResp extends PersonResp { private Integer studentId; private Integer score; public StudentResp() { } public Integer getStudentId() { return this.studentId; } public Integer getScore() { return this.score; } public void setStudentId(final Integer studentId) { this.studentId = studentId; } public void setScore(final Integer score) { this.score = score; } public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof StudentResp)) { return false; } else { StudentResp other = (StudentResp)o; if (!other.canEqual(this)) { return false; } else { Object this$studentId = this.getStudentId(); Object other$studentId = other.getStudentId(); if (this$studentId == null) { if (other$studentId != null) { return false; } } else if (!this$studentId.equals(other$studentId)) { return false; } Object this$score = this.getScore(); Object other$score = other.getScore(); if (this$score == null) { if (other$score != null) { return false; } } else if (!this$score.equals(other$score)) { return false; } return true; } } } protected boolean canEqual(final Object other) { return other instanceof StudentResp; } public int hashCode() { int PRIME = true; int result = 1; Object $studentId = this.getStudentId(); int result = result * 59 + ($studentId == null ? 43 : $studentId.hashCode()); Object $score = this.getScore(); result = result * 59 + ($score == null ? 43 : $score.hashCode()); return result; } public String toString() { return "StudentResp(studentId=" + this.getStudentId() + ", score=" + this.getScore() + ")"; } }
看到這里,大多數(shù)同學(xué)應(yīng)該已經(jīng)定位到出現(xiàn)問題的原因了。
最后的toString()方法可以明確的看到這里只取了子類本身的兩個(gè)屬性,并沒有去獲取父類的屬性。
問題原因
通過看編譯后的代碼可以得出@Data不會打印繼承的父類信息是因?yàn)樵撟⒔獗旧碜饔糜虻膯栴},@Data注解在編譯時(shí)會自動給實(shí)體類添加@Setter,@Getter,@ToString等方法。
但是@Data注解的作用域只在當(dāng)前類中,所以最終打印的時(shí)候只會打印出當(dāng)前類(子類)的信息。
即使子類擁有的是全屬性,但是打印不會顯示父類信息。
解決方式
本文介紹兩種解決方案。
- 第一種:在子類上添加@ToString(callSuper = true)注解,該注解會將父類的屬性跟子類的屬性一起生成toString;
- 第二種:不使用@Data注解,使用@Setter,@Getter注解,在父類中重寫toString()方法并用JSON的方式打印。
1.子類添加@ToString(callSuper = true)注解
@Data @ToString(callSuper = true) public class StudentResp extends PersonResp { /** * 學(xué)號 */ private Integer studentId; /** * 成績 */ private Integer score; }
打印子類
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學(xué)生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風(fēng)清揚(yáng)"); studentResp.setAge(18); //學(xué)生子類 System.out.println(studentResp); }
結(jié)果可以看到父類信息
再看看target中子類編譯后的代碼
public class StudentResp extends PersonResp { private Integer studentId; private Integer score; public StudentResp() { } public Integer getStudentId() { return this.studentId; } public Integer getScore() { return this.score; } public void setStudentId(final Integer studentId) { this.studentId = studentId; } public void setScore(final Integer score) { this.score = score; } public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof StudentResp)) { return false; } else { StudentResp other = (StudentResp)o; if (!other.canEqual(this)) { return false; } else { Object this$studentId = this.getStudentId(); Object other$studentId = other.getStudentId(); if (this$studentId == null) { if (other$studentId != null) { return false; } } else if (!this$studentId.equals(other$studentId)) { return false; } Object this$score = this.getScore(); Object other$score = other.getScore(); if (this$score == null) { if (other$score != null) { return false; } } else if (!this$score.equals(other$score)) { return false; } return true; } } } protected boolean canEqual(final Object other) { return other instanceof StudentResp; } public int hashCode() { int PRIME = true; int result = 1; Object $studentId = this.getStudentId(); int result = result * 59 + ($studentId == null ? 43 : $studentId.hashCode()); Object $score = this.getScore(); result = result * 59 + ($score == null ? 43 : $score.hashCode()); return result; } public String toString() { return "StudentResp(super=" + super.toString() + ", studentId=" + this.getStudentId() + ", score=" + this.getScore() + ")"; } }
可以明確的看到最后的toString()方法中多了一個(gè)super.toString()方法,將父類的信息打印出來
2.不使用@Data注解,使用@Setter,@Getter注解,在父類中重寫toString()方法并用JSON的方式打印。
子類使用@Setter,@Getter注解
@Getter @Setter public class StudentResp extends PersonResp { /** * 學(xué)號 */ private Integer studentId; /** * 成績 */ private Integer score; }
父類中重寫toString()方法并用JSON的方式打印
@Data public class PersonResp { /** * 姓名 */ private String name; /** * 年齡 */ private Integer age; @Override public String toString() { return JSON.toJSONString(this); } }
打印子類
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學(xué)生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風(fēng)清揚(yáng)"); studentResp.setAge(18); //學(xué)生子類 System.out.println(studentResp); }
結(jié)果也可以看到父類信息
總結(jié)
這個(gè)問題本身不算是個(gè)大問題,延伸出來更為重要的是我們解決問題的思路。因?yàn)閺谋举|(zhì)上來說屬性本身都是存在的,只是沒打印出來。
但是遇到這個(gè)問題的時(shí)候第一反應(yīng)都是,明明繼承了父類,為啥父類的值會沒有,從而會帶偏我們?nèi)ソ鉀Q問題方向,遇到此類問題,第一我們應(yīng)該先確認(rèn)問題的本質(zhì),到底有沒有給上值,確認(rèn)了已經(jīng)給上值,就說明只是打印的問題,進(jìn)而去編譯后的代碼中查看為啥沒打印出來,最終定位到問題從而解決問題。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Struts2攔截器Interceptor的原理與配置實(shí)例詳解
攔截器是一種AOP(面向切面編程)思想的編程方式.它提供一種機(jī)制是開發(fā)者能夠把相對獨(dú)立的代碼抽離出來,配置到Action前后執(zhí)行。下面這篇文章主要給大家介紹了關(guān)于Struts2攔截器Interceptor的原理與配置的相關(guān)資料,需要的朋友可以參考下。2017-11-11java中l(wèi)ist使用時(shí)需避免的場景總結(jié)
眾所周知,Java為開發(fā)者提供了多種集合類的實(shí)現(xiàn),其中幾乎所有業(yè)務(wù)代碼都需要用到List,但List的錯誤使用也會導(dǎo)致諸多問題,所以本文我們就來看一看幾個(gè)錯誤使用List的場景吧2023-10-10Java的@Transactional、@Aysnc、事務(wù)同步問題詳解
這篇文章主要介紹了Java的@Transactional、@Aysnc、事務(wù)同步問題詳解,現(xiàn)在我們需要在一個(gè)業(yè)務(wù)方法中插入一個(gè)用戶,這個(gè)業(yè)務(wù)方法我們需要加上事務(wù),然后插入用戶后,我們要異步的方式打印出數(shù)據(jù)庫中所有存在的用戶,需要的朋友可以參考下2023-11-11SpringBoot Nacos實(shí)現(xiàn)自動刷新
這篇文章主要介紹了SpringBoot Nacos實(shí)現(xiàn)自動刷新,Nacos(Dynamic Naming and Configuration Service)是阿里巴巴開源的一個(gè)動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺2023-01-01淺談Java finally語句到底是在return之前還是之后執(zhí)行(必看篇)
下面小編就為大家?guī)硪黄獪\談Java finally語句到底是在return之前還是之后執(zhí)行(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06