解決lombok的@Data注解無法打印繼承的父類信息問題
問題場景
子類StudentResp繼承父類PersonResp,子類也擁有了父類的屬性。
給子類中繼承的父類屬性的賦值,但是打印了以后只會顯示子類信息,父類信息不顯示。
- 子類:學生類繼承父類人員類
@Data public class StudentResp extends PersonResp { /** * 學號 */ 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(); //學生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風清揚"); studentResp.setAge(18); //打印學生子類信息 System.out.println(studentResp); }
打印出來只有子類自己的屬性,父類的屬性沒有出來
問題分析
單獨獲取子類中父類的信息(name跟age),觀察打印看有沒有值
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風清揚"); studentResp.setAge(18); //打印父類信息 System.out.println("姓名:" + studentResp.getName()); System.out.println("年齡:" + studentResp.getAge()); }
打印出來發(fā)現(xiàn)是有值的
確認了繼承本身是沒有問題的,繼承的父類的值都可以給上,也能獲取到,隨后直接打開target對應目錄下的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ù)同學應該已經(jīng)定位到出現(xiàn)問題的原因了。
最后的toString()方法可以明確的看到這里只取了子類本身的兩個屬性,并沒有去獲取父類的屬性。
問題原因
通過看編譯后的代碼可以得出@Data不會打印繼承的父類信息是因為該注解本身作用域的問題,@Data注解在編譯時會自動給實體類添加@Setter,@Getter,@ToString等方法。
但是@Data注解的作用域只在當前類中,所以最終打印的時候只會打印出當前類(子類)的信息。
即使子類擁有的是全屬性,但是打印不會顯示父類信息。
解決方式
本文介紹兩種解決方案。
- 第一種:在子類上添加@ToString(callSuper = true)注解,該注解會將父類的屬性跟子類的屬性一起生成toString;
- 第二種:不使用@Data注解,使用@Setter,@Getter注解,在父類中重寫toString()方法并用JSON的方式打印。
1.子類添加@ToString(callSuper = true)注解
@Data @ToString(callSuper = true) public class StudentResp extends PersonResp { /** * 學號 */ private Integer studentId; /** * 成績 */ private Integer score; }
打印子類
public static void main (String[] args) { StudentResp studentResp = new StudentResp(); //學生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風清揚"); studentResp.setAge(18); //學生子類 System.out.println(studentResp); }
結果可以看到父類信息
再看看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()方法中多了一個super.toString()方法,將父類的信息打印出來
2.不使用@Data注解,使用@Setter,@Getter注解,在父類中重寫toString()方法并用JSON的方式打印。
子類使用@Setter,@Getter注解
@Getter @Setter public class StudentResp extends PersonResp { /** * 學號 */ 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(); //學生子類賦值 studentResp.setStudentId(1000000000); studentResp.setScore(92); //父類賦值 studentResp.setName("風清揚"); studentResp.setAge(18); //學生子類 System.out.println(studentResp); }
結果也可以看到父類信息
總結
這個問題本身不算是個大問題,延伸出來更為重要的是我們解決問題的思路。因為從本質(zhì)上來說屬性本身都是存在的,只是沒打印出來。
但是遇到這個問題的時候第一反應都是,明明繼承了父類,為啥父類的值會沒有,從而會帶偏我們?nèi)ソ鉀Q問題方向,遇到此類問題,第一我們應該先確認問題的本質(zhì),到底有沒有給上值,確認了已經(jīng)給上值,就說明只是打印的問題,進而去編譯后的代碼中查看為啥沒打印出來,最終定位到問題從而解決問題。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Struts2攔截器Interceptor的原理與配置實例詳解
攔截器是一種AOP(面向切面編程)思想的編程方式.它提供一種機制是開發(fā)者能夠把相對獨立的代碼抽離出來,配置到Action前后執(zhí)行。下面這篇文章主要給大家介紹了關于Struts2攔截器Interceptor的原理與配置的相關資料,需要的朋友可以參考下。2017-11-11Java的@Transactional、@Aysnc、事務同步問題詳解
這篇文章主要介紹了Java的@Transactional、@Aysnc、事務同步問題詳解,現(xiàn)在我們需要在一個業(yè)務方法中插入一個用戶,這個業(yè)務方法我們需要加上事務,然后插入用戶后,我們要異步的方式打印出數(shù)據(jù)庫中所有存在的用戶,需要的朋友可以參考下2023-11-11淺談Java finally語句到底是在return之前還是之后執(zhí)行(必看篇)
下面小編就為大家?guī)硪黄獪\談Java finally語句到底是在return之前還是之后執(zhí)行(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06