实体类继承某类后覆盖重写toString方法无法打印所有的实体

发布时间 2023-07-21 11:49:20作者: 炸天帮帮主

发生缘由

  • SpringBoot项目

运行环境

  • 电脑系统:win10

  • jdk版本:jdk-8

  • SpringBoot版本:v2.7.13

  • MP版本:3.5.3

<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <!-- 非SpringBoot项目可以加上版本号,SpringBoot项目无需加 -->
   <version>1.18.12</version>
   <!-- 指定依赖作用范围,在编译和测试的环境作用,不会被打包 -->
   <scope>provided</scope>
</dependency>

项目模拟

/**
* Emp实体类
* 1.Data注解:包含了Setter、Getter、ToString、EqualsAndHashCode等注解
* 2.NoArgsConstructor注解:无参构造函数注解
* 3.AllArgsConstructor注解:全参构造函数注解
* 4.Accessors(chain = true):给set方法开启链式编程调用
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Emp {
   private Integer eid;
   private String empName;
   private Integer age;
   private Character sex;
   private String email;
   private Integer did;
   private Integer version;
}
@Data
@Accessors(chain = true)
public class Dept {
   private Integer did;
   private String deptName;
}
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class EmpDto extends Emp {
   private Dept dept;
}
@Test
public void testEmpDtoToString() {
   // 创建Dept实体类
   Dept dept = new Dept();
   dept.setDid(1).setDeptName("A");
   // 创建EmpDto数据传输类
   EmpDto empDto = new EmpDto();
   empDto.setDept(dept);
   empDto.setEid(1).setDid(1).setEmail("666@qq.com").setSex('男').setAge(21).setVersion(1);
   // 调用toString方法打印empDto可是发现打印结果为:EmpDto(dept=Dept(did=1, deptName=A))
   System.out.println(empDto);
}

可以发现打印结果并非是我们想要的EmpDto{dept=Dept(did=1, deptName=A), eid=1, empName='null', age=21, sex=男, email='666@qq.com', did=1, version=1},而是EmpDto(dept=Dept(did=1, deptName=A)),所有从Emp实体类继承来的属性都没有打印值。

解决方案

出现该问题的原因主要是访问修饰符的问题,我们给 Emp 实体类中的所有属性设置的访问修饰都是 private,这导致了 EmpDao 数据传输类并没有办法继承这些属性,也就导致了无法打印值了。

所以究其根本就是现在 EmpDao 类里面并没有继承下来 Emp 实体类中的属性,直到原因,那么就可以来解决了。对此,一共有两种方法:调用 getter 方法、修改访问修饰符。

调用 getter 方法

既然没有该属性,那么我们可以调用该属性的 getter 方法来获取值。

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class EmpDto extends Emp {
   private Dept dept;

   @Override
   public String toString() {
       return "EmpDto{" +
               "dept=" + dept +
               ", eid=" + getEid() +
               ", empName='" + getEmpName() + '\'' +
               ", age=" + getAge() +
               ", sex=" + getSex() +
               ", email='" + getEmail() + '\'' +
               ", did=" + getDid() +
               ", version=" + getVersion() +
               '}';
  }
}

修改访问修饰符

既然是 private 访问修饰符导致这些属性无法被继承,那么换一种即可!

修饰符当前类同一包内子孙类(同一包)子孙类(不同包)其他包
public Y Y Y Y Y
protected Y Y Y Y/N N
default Y Y Y N N
private Y N N N N

这里换成 protected 来修饰

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Emp {
   protected Integer eid;
   protected String empName;
   protected Integer age;
   protected Character sex;
   protected String email;
   protected Integer did;
   protected Integer version;
}

只操作这一步发现还是不可以的,这是因为@Data生成的toString()方法默认并不会打印父类中的属性,所以这里需要我们手动生成一下toString()

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class EmpDto extends Emp {
   private Dept dept;

   // IDEA快捷键:Alt + Ins,然后选择toString(),最后选择所有的属性即可
   @Override
   public String toString() {
       return "EmpDto{" +
               "dept=" + dept +
               ", eid=" + eid +
               ", empName='" + empName + '\'' +
               ", age=" + age +
               ", sex=" + sex +
               ", email='" + email + '\'' +
               ", did=" + did +
               ", version=" + version +
               '}';
  }
}