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

Java受限长度字符串类实现及内存优化问题咨询

问题与优化方案

问题背景

需要实现一个类似String的自定义类型(Java无法继承String),用于约束联系人姓名:

  • 名:长度不超过10字符,不可为空
  • 姓:长度不超过15字符,不可为空

原代码试图将LimitedString的约束字段(描述、长度限制、是否可空)设为static final以减少集合中联系人的内存占用,但该方案无法正常工作——静态字段属于类级别,所有实例共享,会导致不同约束的实例(如名和姓)互相覆盖约束规则,校验逻辑完全失效。

核心问题分析

  1. 静态字段滥用:descriptor、minimumLength、maximumLength、nullable被定义为static final,所有LimitedString实例共用这些值。创建firstName和lastName实例时,后创建的实例会覆盖静态字段值,导致校验规则混乱。
  2. 构造方法错误:无初始值的构造方法调用setValue(value)时,value未初始化,直接触发空指针或非法参数异常。
  3. 代码规范问题:ToString()不符合Java驼峰命名规范(应为toString());String.format占位符错误(@s应为%s)。

优化方案

方案思路

将约束规则封装为独立的配置类,让相同约束的LimitedString实例共享该配置对象——既保证每个实例有正确的约束规则,又能减少内存占用(相同约束的实例共用一个配置,无需重复存储约束字段)。同时修复代码中的错误,完善校验逻辑。

修改后的代码

1. 约束配置类 StringConstraint

package Models;

public class StringConstraint {
    private final String descriptor;
    private final int minimumLength;
    private final int maximumLength;
    private final boolean nullable;

    public StringConstraint(String descriptor, int minimumLength, int maximumLength, boolean nullable) {
        if (minimumLength < 0) {
            throw new IllegalArgumentException("最小长度不能小于0");
        }
        if (minimumLength > maximumLength) {
            throw new IllegalArgumentException("最小长度不能大于最大长度");
        }
        this.descriptor = descriptor;
        this.minimumLength = minimumLength;
        this.maximumLength = maximumLength;
        this.nullable = nullable;
    }

    // Getter方法
    public String getDescriptor() {
        return descriptor;
    }

    public int getMinimumLength() {
        return minimumLength;
    }

    public int getMaximumLength() {
        return maximumLength;
    }

    public boolean isNullable() {
        return nullable;
    }
}

2. 优化后的 LimitedString 类

package Models;

public class LimitedString {
    private String value;
    private final StringConstraint constraint;

    // 带初始值的构造方法
    public LimitedString(String value, StringConstraint constraint) {
        this.constraint = constraint;
        setValue(value);
    }

    // 空构造方法(用于后续设置值)
    public LimitedString(StringConstraint constraint) {
        this.constraint = constraint;
    }

    @Override
    public String toString() {
        return value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        // 校验空值
        if (value == null && !constraint.isNullable()) {
            throw new IllegalArgumentException(constraint.getDescriptor() + " 不能为空");
        }
        // 校验长度
        if (value != null) {
            int length = value.length();
            if (length < constraint.getMinimumLength() || length > constraint.getMaximumLength()) {
                throw new IllegalArgumentException(String.format(
                    "%s 长度必须在 %d 到 %d 字符之间",
                    constraint.getDescriptor(),
                    constraint.getMinimumLength(),
                    constraint.getMaximumLength()
                ));
            }
        }
        this.value = value;
    }

    public StringConstraint getConstraint() {
        return constraint;
    }
}

3. 优化后的 Contact 类

package Models;

public class Contact {
    // 定义全局共享的约束实例,所有Contact的firstName/lastName共用
    private static final StringConstraint FIRST_NAME_CONSTRAINT = new StringConstraint("名", 1, 10, false);
    private static final StringConstraint LAST_NAME_CONSTRAINT = new StringConstraint("姓", 1, 15, false);

    private final LimitedString firstName;
    private final LimitedString lastName;

    // 构造方法直接初始化值
    public Contact(String firstName, String lastName) {
        this.firstName = new LimitedString(firstName, FIRST_NAME_CONSTRAINT);
        this.lastName = new LimitedString(lastName, LAST_NAME_CONSTRAINT);
    }

    // Getter方法(若不需要修改姓名,可去掉Setter,让Contact不可变)
    public String getFirstName() {
        return firstName.getValue();
    }

    public String getLastName() {
        return lastName.getValue();
    }

    // 若需要支持修改姓名,添加Setter
    public void setFirstName(String firstName) {
        this.firstName.setValue(firstName);
    }

    public void setLastName(String lastName) {
        this.lastName.setValue(lastName);
    }
}

优化说明

  1. 内存优化:通过StringConstraint共享约束规则,所有Contact的firstName共用同一个FIRST_NAME_CONSTRAINT实例,lastName同理,避免每个LimitedString实例重复存储约束字段,有效减少内存占用。
  2. 逻辑正确性:每个LimitedString实例持有独立的约束引用,不同类型的字段(名/姓)不会互相覆盖规则,校验逻辑正常工作。
  3. 代码规范:修复了toString()命名、占位符错误等问题,完善了异常提示信息。
  4. 可扩展性:新增约束类型时,只需创建新的StringConstraint实例,无需修改LimitedString类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:20:53