You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Clock类构造方法赋值时hour可传入超12的非法值问题

问题根因

你写的范围校验逻辑只存在于各字段的setXxx方法中,全参构造方法完全没有做任何合法性判断,是直接把外部传入的参数赋值给私有字段的,传入hour=15这类非法值时会直接跳过校验,生成带非法状态的对象。
你观察到的minute字段暂未出现越界问题纯粹是测试用例覆盖不全的巧合:一方面你没在测试构造方法时传入超出分钟范围的值,另一方面你写的setMinute校验本身就有逻辑错误——12小时制时钟分钟合法范围是0-59,你写的判断条件允许值为60的非法输入存入。
你之前自行修改代码后触发更多异常,通常是两个原因导致的:一是重复在构造方法里写校验逻辑时漏了边界判断,二是没有处理入参为null的场景,比如setPeriod里直接写period.equals("PM"),如果传入null值会直接触发空指针。

修复方案
  • 全参构造方法不要直接给字段赋值,统一调用已经实现好的setXxx方法完成赋值,从根源上避免校验逻辑重复写、两边规则不一致的问题。
  • 修正setMinute的判断上界,把<=60改成<=59;修正所有字符串入参的equals判断写法,把常量放在equals前面,避免入参为null时触发空指针,比如把period.equals("PM")改成"PM".equals(period)。
  • 构造方法中需要处理setXxx返回false的非法入参场景,要么直接抛出参数非法的异常明确提示调用方,要么回退到该字段的默认值,绝对不能让对象带着非法状态完成初始化。
修复后参考代码
public class Clock {

    private int hour;
    private int minute;
    private String period;
    private String timeZone;

    public Clock() {
        this.hour = 12;
        this.minute = 0;
        this.period = "AM";
        this.timeZone = "Eastern";
    }

    public Clock(int hour, int minute, String period, String timeZone) {
        // 先初始化默认值,避免某一步校验失败出现字段值混乱
        this();
        // 复用setter的校验逻辑赋值,非法入参直接抛出明确异常
        if (!this.setHour(hour)) {
            throw new IllegalArgumentException("小时取值范围必须为1-12");
        }
        if (!this.setMinute(minute)) {
            throw new IllegalArgumentException("分钟取值范围必须为0-59");
        }
        if (!this.setPeriod(period)) {
            throw new IllegalArgumentException("时段仅支持传入AM/PM");
        }
        if (!this.setTimeZone(timeZone)) {
            throw new IllegalArgumentException("时区仅支持Eastern/Central/Mountain/Pacific");
        }
    }
    
    public boolean setHour(int hour) {
        if (hour >= 1 && hour <= 12) {
            this.hour = hour;
            return true;
        } else {
            return false;
        }
    }

    public int getHour() {
        return this.hour;
    }

    public boolean setMinute(int minute) {
        // 修正上界错误:分钟最大为59
        if (minute >= 0 && minute <= 59) {
            this.minute = minute;
            return true;
        } else {
            return false;
        }
    }

    public int getMinute() {
        return this.minute;
    }

    public boolean setPeriod(String period) {
        // 修正空指针风险:常量在前调用equals
        if ("PM".equals(period) || "AM".equals(period)) {
            this.period = period;
            return true;
        } else {
            return false;
        }
    }

    public String getPeriod() {
        return this.period;
    }

    public boolean setTimeZone(String timeZone) {
        // 修正空指针风险:常量在前调用equalsIgnoreCase
        if ("Eastern".equalsIgnoreCase(timeZone) || "Central".equalsIgnoreCase(timeZone) ||
            "Mountain".equalsIgnoreCase(timeZone) || "Pacific".equalsIgnoreCase(timeZone)) {
            this.timeZone = timeZone;
            return true;
        } else {
            return false;
        }
    }

    public String getTimeZone() {
        return this.timeZone;
    }
}

内容的提问来源于stack exchange,提问作者user19124593

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:45:40