Pie*_*ero 3 java constructor record java-17
我想知道如何重写这个类
public class ClassA {
private final String foo;
private final String bar;
public ClassA(String foo) {
this.foo = foo;
this.bar = foo.toUpperCase();
}
// getters...
}
Run Code Online (Sandbox Code Playgroud)
作为记录类。
我能做到的最好的就是这个
public record ClassA(String foo, String bar) {
public ClassA(String foo) {
this(foo, foo.toUpperCase());
}
}
Run Code Online (Sandbox Code Playgroud)
问题是这个解决方案创建了两个构造函数,而我只想要一个接受字符串 foo 的构造函数
这更多的是对/sf/answers/5119627061/的回应,而不是任何关于如何执行此操作的建议。引用的答案比OP的版本更好,但它仍然颠覆了记录的精神,即它们是名义元组,也许带有一些约束组件的不变量。
下面是一个很好地使用具有不变量的记录的示例:
record Range(int low, int hi) {
public Range {
if (low > hi) throw new IllegalArgumentException();
}
}
Run Code Online (Sandbox Code Playgroud)
规范构造函数验证参数,拒绝无效参数,然后,整个过程就像某个元组的透明、不可变容器一样运行,派生出有用的 API(构造函数、解构模式(从 Java 19 开始)、访问器、equals、hashCode、 toString) 来自元组。
这里的等效方法是诚实地承认您正在编写的内容是任意字符串的元组及其大写版本:
record StringWithCachedUppercase(String value, String uppercased) {
public StringWithCachedUppercase {
if (!uppercased.equals(value.toUpperCase(Local.ROOT)))
throw new IllegalArgumentException();
}
public StringWithCachedUppercase(String value) {
this(value, value.toUpperCase(Locale.ROOT));
}
}
Run Code Online (Sandbox Code Playgroud)
为什么链接的答案不太理想?因为规范的构造函数拉得很快,并且破坏了new XyRecord(x, y).y()应该返回与传递到构造函数中的内容相关的东西的合理直觉y。也许它是一个标准化版本,但它应该是可识别的——在链接的答案中,它被完全忽略了。
有些人可能会犹豫“但是你要计算大写版本两次”,但这并不是错误使用该机制的借口。(而且,由于此类事情的全部理由是“我想缓存这个看似昂贵的计算”,所以使用它的唯一目的是如果您要多次请求大写版本。在这种情况下,O(1) 额外的构建成本不相关。)
此示例说明了一种常见情况,其中记录是“几乎”,即“元组,但缓存派生数量”。我们在记录设计过程中对这个案例进行了详细的考虑,但最终得出的结论是,它应该保留在记录设计中心之外。
如果您确实对缓存派生量感兴趣,那么可以延迟计算它们并将其缓存在 WHM 中:
record StringWrapper(String s) {
static Map<StringWrapper, String> uppers = Collections.synchronizedMap(new WeakHashMap<>());
public String uppercase() {
return uppers.computeIfAbsent(this, r -> r.s.toUpperCase(Locale.ROOT));
}
}
Run Code Online (Sandbox Code Playgroud)