构造方法参数顺序引发异常及Setter相关技术疑问
构造方法调用Setter出现异常行为的问题
为避免代码重复,我在Java构造方法中调用Setter方法,原本认为传入正确参数时参数顺序不会影响执行结果,但实际出现了不符合预期的行为。
相关代码
public class Wall { private double width; private double height; public Wall() {} public Wall(double width, double height) { this.setHeight(height); // 调用Setter设置字段,但出现异常行为 this.setWidth(width); // 看起来没被执行? } public double getWidth() { return width; } public void setWidth(double width) { if (width <= 0) { this.width = 0; System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0); } else { this.width = width; System.out.println("The width of the wall is updated to :" + width); } } public double getHeight() { return height; } public void setHeight(double height) { if (height <= 0) { this.height = 0; System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0); } else { this.height = height; System.out.println("The height of the wall is updated to :" + height); } } public double getArea() { return width * height; } }
输出结果
原构造方法参数顺序下的输出
The width of the wall is updated to :10.0 // 符合预期 INVALID VALUE - The width of the wall is updated to :0.0 // 不符合预期
构造方法参数顺序反转后的输出
INVALID VALUE - The width of the wall is updated to :0.0 // 符合预期 The height of the wall is updated to :10.0 // 符合预期
疑问
- 构造方法中的Setter方法为何并非全部被调用?
- 这些Setter方法能否设为静态并对正在创建的对象进行操作?
- 这种场景下的正确实现方式是什么?
解答
1. 所有Setter都被调用了,是输出信息错误导致误解
你在setHeight方法里犯了一个低级错误:当height参数非法时,打印的提示文本是**"INVALID VALUE - The width of the wall is updated to :"**,这明显是复制setWidth的代码时没修改字段名称。
比如你传入参数(10.0, -5.0)时:
- 先执行
setHeight(-5.0),触发非法判断,修改的是height字段为0,但错误打印了"width更新为0"的信息 - 接着执行
setWidth(10.0),正常修改width字段并打印正确信息
但因为提示文本错误,你误以为setWidth没被调用,实际上两个Setter都执行了,只是输出信息混淆了操作的字段。
2. 不能将Setter设为静态来操作实例
静态方法属于类本身,不属于任何具体对象,在静态方法里无法直接访问非静态的实例变量(width和height都是实例变量),也不能使用this关键字指向当前正在创建的对象。所以静态Setter根本无法修改实例的字段,这个思路不可行。
3. 两种正确实现方案
方案一:提取统一校验逻辑到私有辅助方法
把参数校验的逻辑抽成一个私有方法,构造方法和Setter都调用这个方法,既避免代码重复,又能保证逻辑一致:
public class Wall { private double width; private double height; public Wall() {} public Wall(double width, double height) { this.width = validateDimension(width, "width"); this.height = validateDimension(height, "height"); } public double getWidth() { return width; } public void setWidth(double width) { this.width = validateDimension(width, "width"); } public double getHeight() { return height; } public void setHeight(double height) { this.height = validateDimension(height, "height"); } public double getArea() { return width * height; } // 私有辅助方法:统一处理维度参数的校验和提示 private double validateDimension(double value, String dimensionName) { if (value <= 0) { System.out.printf("INVALID VALUE - The %s of the wall is updated to :%.1f%n", dimensionName, 0.0); return 0; } else { System.out.printf("The %s of the wall is updated to :%.1f%n", dimensionName, value); return value; } } }
方案二:修正Setter的错误后继续使用构造调用Setter
如果你坚持用构造方法调用Setter,首先要修正setHeight里的错误提示文本,确保输出信息准确:
public void setHeight(double height) { if (height <= 0) { this.height = 0; // 将这里的width改为height,修正提示文本 System.out.println("INVALID VALUE - The height of the wall is updated to :" + 0.0); } else { this.height = height; System.out.println("The height of the wall is updated to :" + height); } }
注意:如果这个类会被子类继承,构造方法调用Setter可能引发意外(父类构造执行时子类还未完成初始化,若子类覆盖了Setter,会执行子类的逻辑)。如果类不会被继承,这个方案没问题;若涉及继承,优先选方案一。
内容的提问来源于stack exchange,提问作者Taha Sk
相关产品推荐
相关产品推荐

