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