在普通的Java程序里,父类引用指向子类对象时,该引用只能调用父类中定义的方法和变量
例如为HTTP请求创建一个基类CommonResponse
public class CommonResponse {
protected int status;
protected String msg;
public CommonResponse() {
this.status = HttpStatus.OK.value();
this.msg = "Success";
}
public CommonResponse(int status, String msg) {
this.status = status;
this.msg = msg;
}
public String getFileOriName() {
return "I don't have a filename";
}
}
再创建一个子类FileUploadResponse
public class FileUploadResponse extends CommonResponse {
private String fileOriName;
private String filePath;
public FileUploadResponse (String oriName, String filePath) {
super();
fileOriName = oriName;
this.filePath = filePath;
}
public FileUploadResponse(int status, String msg) {
super(status, msg);
}
public String getFileOriName() {
return fileOriName;
}
public String getFilePath() {
return filePath;
}
}
Test Case
/*
* Parent class - CommonResponse
* Child class - FileUploadResponse
*/
@Test
public void lombokTest() throws JsonProcessingException {
CommonResponse fileUploadResponse1 = new FileUploadResponse("file1.txt", "/Users/file1.txt");
System.out.println(fileUploadResponse1.getMsg());
System.out.println(fileUploadResponse1.getFileOriName());
}
结果
Success
file1.txt
首先,getFilePath()
的方法是不存在于这个对象上的
且getFileOriName()
通过重写成功调用了父类中不存在的变量
这个时候如果用jackson将对象转换为json string,转换成的对象会因为get方法的不同而有所不同,如果父类和子类都不写getter,则jackson会报错。
而如果写了getMsg()
和getFileOriName()
,返回的对象则会为msg
和fileOriName
的组合。
{"msg":"Success","fileOriName":"I don't have a filename"}
{"msg":"Success","fileOriName":"file1.txt"}
为父类和子类对象都加上Lombok的@Data标签后,发现子类对父类的重写都依然存在
修改父类
@Data
public class CommonResponse {
protected int status;
protected String msg;
public CommonResponse() {
this.status = HttpStatus.OK.value();
this.msg = "Success";
}
public CommonResponse(int status, String msg) {
this.status = status;
this.msg = msg;
}
public String getFileOriName() {
return "I don't have a filename";
}
}
修改子类
@Data
public class FileUploadResponse extends CommonResponse {
private String fileOriName;
private String filePath;
public FileUploadResponse (String oriName, String filePath) {
super();
fileOriName = oriName;
this.filePath = filePath;
}
public FileUploadResponse(int status, String msg) {
super(status, msg);
}
}
Test Case
/*
* Parent class - CommonResponse
* Child class - FileUploadResponse
*/
@Test
public void lombokTest() throws JsonProcessingException {
CommonResponse fileUploadResponse1 = new FileUploadResponse("file1.txt", "/Users/file1.txt");
System.out.println(fileUploadResponse1.getMsg());
System.out.println(fileUploadResponse1.getFileOriName());
}
结果
Success
file1.txt
我们可以注意到另一件事情,在Lombok默认的@ToString方法里,是不带父类变量的
Test Case
/*
* Parent class - CommonResponse
* Child class - FileUploadResponse
*/
@Test
public void lombokTest() throws JsonProcessingException {
CommonResponse commonResponse = new CommonResponse();
CommonResponse fileUploadResponse1 = new FileUploadResponse("file1.txt", "/Users/file1.txt");
System.out.println(commonResponse);
System.out.println(fileUploadResponse1);
}
结果
CommonResponse(status=200, msg=Success)
FileUploadResponse(fileOriName=file1.txt, filePath=/Users/file1.txt)
但如果使用Jackson将对象转化为json string,子类继承父类的变量也会全部被打印出来
Test Case
/*
* Parent class - CommonResponse
* Child class - FileUploadResponse
*/
@Test
public void lombokTest() throws JsonProcessingException {
CommonResponse commonResponse = new CommonResponse();
CommonResponse fileUploadResponse1 = new FileUploadResponse("file1.txt", "/Users/file1.txt");
System.out.println(commonResponse);
System.out.println(fileUploadResponse1);
System.out.println(JsonConverter.objToJson(commonResponse));
System.out.println(JsonConverter.objToJson(fileUploadResponse1));
}
/*
* 002.对象转换成json
* @param:传入对象
* @return:json字符串
*/
public static String objToJson(Object obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(obj);
}
结果
CommonResponse(status=200, msg=Success)
FileUploadResponse(fileOriName=file1.txt, filePath=/Users/file1.txt)
{"status":200,"msg":"Success","fileOriName":"I don't have a filename"}
{"status":200,"msg":"Success","fileOriName":"file1.txt","filePath":"/Users/file1.txt"}
如果想要在@ToString时打印父类变量,或者在比较时使用父类变量,则需要加上callSuper = true
的注释
修改子类
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper=true)
public class FileUploadResponse extends CommonResponse {
private String fileOriName;
private String filePath;
public FileUploadResponse (String oriName, String filePath) {
super();
fileOriName = oriName;
this.filePath = filePath;
}
public FileUploadResponse(int status, String msg) {
super(status, msg);
}
}
重跑Test结果
CommonResponse(status=200, msg=Success)
FileUploadResponse(super=CommonResponse(status=200, msg=Success), fileOriName=file1.txt, filePath=/Users/file1.txt)
{"status":200,"msg":"Success","fileOriName":"I don't have a filename"}
{"status":200,"msg":"Success","fileOriName":"file1.txt","filePath":"/Users/file1.txt"}
References
父类引用指向子类对象
搜索资料过程中发现的有用的避雷贴
Lombok插件安装与使用说明
浅析JavaBean继承后重写父类属性和lombok注解带来的问题和解决方案
网友评论