如何使toString()方法返回Super Class私有字段及其实例字段?
有没有办法让toString()
包含超class
私有字段? 我尝试添加super.toString()
,但没有用。
请参阅下面的代码
Employee.java
package test; public class Employee { private String name; private int id; private double salary; public Employee(String name, int id, double salary) { super(); this.name = name; this.id = id; this.salary = salary; } public double getSalary() { return salary; } @Override public String toString() { return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]"; } public static void main(String[] args) { Employee e=new Employee("Joe", 14, 5000); System.out.println(e); Manager m=new Manager("Bill", 23, 5000, 10); System.out.println(m); System.out.println("Employee Salary is "+e.getSalary()+"\nManager salary is "+m.getSalary()); } }
Manager.java
package test; public class Manager extends Employee{ private double bonus; public Manager(String name, int id, double salary,int bonus) { super(name, id, salary); this.bonus=bonus; } public double getSalary() { double baseSalary=super.getSalary(); return (baseSalary+baseSalary*(bonus/100)); } @Override public String toString() { return(this.getClass().getName()+" ["+super.toString().substring((this.getClass().getSuperclass().getName().length()-3 ), (super.toString().length())-1)+", bonus="+bonus+"]"); //didn't work //super.toString(); //return "Manager [bonus=" + bonus + "]"; } }
产量
Employee [name=Joe, id=14, salary=5000.0] test.Manager [name=Bill, id=23, salary=5000.0, bonus=10.0] Employee Salary is 5000.0 Manager salary is 5500.0
这是我能做的最好的,连接super.toString()
+’一组字符串’,当然这是凌乱的,还有其他方法,即使语言规范不允许它,eclipse有一些设施要做注意 :我使用eclipse生成toString方法,我可以通过它告诉eclipse包含超类字段,
换句话说,我可以替换这个凌乱的代码
return(this.getClass().getName()+" ["+super.toString().substring((this.getClass().getSuperclass().getName().length()-3 ), (super.toString().length())-1)+", bonus="+bonus+"]");
通过让eclipse自动化流程并生成一个合适的方法来实现它?
如果在超类中创建getter和setter,则可以通过这些方法访问变量。 其他可能性是将可见性从私有更改为受保护
第一个解决方案就像这样
雇员
public class Employee { private String name; private int id; private double salary; public Employee(String name, int id, double salary) { super(); this.name = name; this.id = id; this.salary = salary; } public double getSalary() { return salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public void setSalary(double salary) { this.salary = salary; } @Override public String toString() { return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]"; } }
经理
public class Manager extends Employee { private double bonus; public Manager(String name, int id, double salary, int bonus) { super(name, id, salary); this.bonus = bonus; } public double getSalary() { double baseSalary = super.getSalary(); return (baseSalary + baseSalary * (bonus / 100)); } @Override public String toString() { return "Manager [name=" + getName() + ", id=" + getId() + ", salary=" + getSalary() + ", bonus=" + bonus + "]"; } }
第二个(使用受保护的)
雇员
public class Employee { protected String name; protected int id; protected double salary; public Employee(String name, int id, double salary) { super(); this.name = name; this.id = id; this.salary = salary; } public double getSalary() { return salary; } @Override public String toString() { return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]"; } }
经理
public class Manager extends Employee { protected double bonus; public Manager(String name, int id, double salary, int bonus) { super(name, id, salary); this.bonus = bonus; } public double getSalary() { double baseSalary = super.getSalary(); return (baseSalary + baseSalary * (bonus / 100)); } @Override public String toString() { return "Manager [name=" + name + ", id=" + id + ", salary=" + salary + ", bonus=" + bonus + "]"; } }
就个人而言,我会使用getter / setter方法,但这取决于你。
编辑:在eclipse中添加到eclipse生成的toString()
。 你似乎无法使用getter和setter生成它(只是快速查看,你可以在这里看到一些文档。我弄清楚你是如何编辑生成toString()
时使用的代码模板所以它包括来自超类的toString()
。
当您进入generate toString()对话框时,旁边有一个“String Format”字段,其中包含
。 单击编辑按钮时,可以创建新的代码模板。 此模板自动保存
,看起来像这样:
${object.className} [${member.name()}=${member.value}, ${otherMembers}]
你必须添加的东西最后是以下内容
[super: ${object.superToString}]
这样它就会显示超类的toString()
你可以让eclipse生成它,但它看起来不像你想要它。
创建此代码:
public String toString() { return "Manager [bonus=" + bonus + ", toString()=" + super.toString() + "]"; }
哪打印出来:
经理[奖金= 10.0,toString()=员工[name = Bill,id = 23,salary = 5000.0]]
这是你可以让eclipse为你生成的最多。
你可以把它清理一下,看起来像这样
public String toString() { return "Manager [bonus=" + bonus + "] is a " + super.toString(); }
哪个会打印
经理[奖金= 10.0]是员工[name = Bill,id = 23,salary = 5000.0]
但是,您的自定义解决方案也可以。 那么为什么不使用呢?
你可以这样清理一下:
@Override public String toString() { return "Manager [" + superFieldsFromToString() + ", bonus=" + bonus + "]"; } private String superFieldsFromToString() { String superToString = super.toString(); int superClassNameLength = getClass().getSuperclass().getSimpleName().length(); int fieldStartIdx = superClassNameLength + 2; // + 2 removes " [" int fieldEndIdx = superToString.length() - 1; // - 1 removes "]" return superToString.substring(fieldStartIdx , fieldEndIdx); }
哪个输出
经理[name = Bill,id = 23,salary = 5000.0,bonus = 10.0]
正如其他人所提到的,唯一的其他选择是使用reflection来访问私有字段,使字段受到保护或创建公共getter。
我不建议做任何这些,因为你的类设计不应该由调试输出定义。
不会。因为如果您可以直接访问超类的私有字段,那么这些字段将不是私有的。
有些事情没有意义:
-
您的所有字段都是原始字段和不可变字段,因此您可以使用getter安全地发布它们(用于Concurenecy目的)。
-
如果你想到工资,id,奖金私有因为这些不应该被知道(因此不提供getter),那么为什么要提供一个显示这个秘密信息的toString。 如果toString仅用于可视化测试目的,那么考虑使它们受到保护,然后在成功测试类后再将它们设置为私有。
否则,你的课程结构有问题,你只是想用语言做一些黑客攻击。
可能的解决方案是为字段创建受保护的getter,以防您不希望字段本身受到保护。
最佳方案
您可以调用超类实例变量的getter并将值放在toString()
。 你甚至可以偷偷摸摸地让getter protected
这样只有子类才能查看变量的值。
懒惰的解决方案
根据超类的设计方式,使字段protected
,这可能是一个坏主意。
馊主意
你也可以使用reflection,但我不会这样做。
为特定目的创建了reflection,以发现在编译时未知的类的function,类似于dlopen和dlsym函数在C中执行的操作。除此之外的任何使用都应该经过严格审查。 ( https://softwareengineering.stackexchange.com/questions/193526/is-it-a-bad-habit-to-overuse-reflection )
如果您无法更改超类的代码(更改成员范围或添加getter),则可以使用JavareflectionAPI访问私有字段:
Manager managerObject = new managerObject(): Employee e = (Employee) managerObject; Field f = e.getClass().getDeclaredField("salary"); f.setAccessible(true); double sal = (double) f.get(e);
- Xuggle和java库路径
- 使用Java SE 10.0.1的Eclipse Oxygen Window Builder错误
- GWT webappcreator创建Maven项目:源附件不包含文件URLClassPath.class的源
- 我的代码在Eclipse中编译但我在运行时获得了一个ClassNotFound如何修复它?
- 无法在项目上执行目标org.apache.maven.plugins:maven-compiler-plugin(default-compile):致命错误编译:找不到tools.jar
- 创建Maven项目,无法解析原型,拒绝连接
- Eclipse在启动配置中使用错误的maven依赖项
- 申请停止后Btld消耗资源?
- 我可以从Eclipse创建的命令行程序运行吗?