Jum*_*p3r 13 java arraylist optional java-8
如何使用Optionals将此函数重写为更多Java 8?或者我应该保持原样?
public void setMemory(ArrayList<Integer> memory) {
if (memory == null)
throw new IllegalArgumentException("ERROR: memory object can't be null.");
if (memory.contains(null))
throw new IllegalArgumentException("ERROR: memory object can't contain null value.");
this.memory = memory;
}
Run Code Online (Sandbox Code Playgroud)
你有一个condition -> throw an exception可以移动到方法的模式:
private void checkOrElseThrow(boolean condition, Supplier<? extends RuntimeException> exceptionSupplier) {
if (condition) {
throw exceptionSupplier.get();
}
}
public void setMemory(List<Integer> memory) {
checkOrElseThrow(memory == null, () -> new IllegalArgumentException("message #1"));
checkOrElseThrow(memory.contains(null), () -> new IllegalArgumentException("message #2"));
this.memory = memory;
}
Run Code Online (Sandbox Code Playgroud)
如果不会更改异常的类型,则仅传递异常消息是合理的(感谢@tobias_k指出它):
private void checkOrElseThrow(boolean condition, String exceptionMessage) {
if (condition) {
throw new IllegalArgumentException(exceptionMessage);
}
}
public void setMemory(List<Integer> memory) {
checkOrElseThrow(memory == null, "message #1");
checkOrElseThrow(memory.contains(null), "message #2");
this.memory = memory;
}
Run Code Online (Sandbox Code Playgroud)
如果你想坚持IllegalArgumentException 并且你在类路径上有guava,你可以使用这个:
Preconditions.checkArgument(memory != null,
"ERROR: memory object can't be null.");
Preconditions.checkArgument(!memory.contains(null),
"ERROR: memory object can't contain null value.");
Run Code Online (Sandbox Code Playgroud)
您不能真正使用Optional此处,因为您需要针对不同条件的不同错误消息.
如果您可以在另一方面收到单个错误消息,则可以执行以下操作:
this.memory = Optional.ofNullable(memory)
.filter(x -> !x.contains(null))
.orElseThrow(() -> new IllegalArgumentException(
"memory object is null or contains null values"));
Run Code Online (Sandbox Code Playgroud)
对于第一种情况,我会使用:
Objects.requireNonNull().
我不认为Optional这null是一种非法价值的方式.
我通常会避免Optional这种情况,因为它往往会模糊正在发生的事情.
但首先我要提一下,原始代码允许调用者保留memory对包含类的内部字段的引用.也许您相信您的呼叫者不会恶意,但调用者可能会意外地重复使用作为参数传递的列表.如果确实如此,尽管进行了细致的参数检查,memory列表最终可能会包含空值.或者,它可能会意外地改变,导致其他故障.
解决方案是制作参数列表的防御副本.直截了当的方法如下:
public void setMemory(ArrayList<Integer> memory) {
if (memory == null)
throw new IllegalArgumentException("memory is null");
List<Integer> temp = new ArrayList<>(memory);
if (temp.contains(null))
throw new IllegalArgumentException("memory contains null");
this.memory = temp;
}
Run Code Online (Sandbox Code Playgroud)
请注意,复制是在temp检查之前制作并存储在本地变量中.显然,在检查列表是否包含空值之前,您不希望存储到字段中.但是包含空值的检查应该在副本上进行,而不是在参数列表上进行,否则,调用者可以在检查之后但在复制之前修改列表.(是的,这是偏执狂.)
如果您不关心确切的异常消息,可以缩短如下:
public void setMemory(ArrayList<Integer> memory) {
List<Integer> temp;
if (memory == null || ((temp = new ArrayList<>(memory)).contains(null)))
throw new IllegalArgumentException("memory is or contains null");
this.memory = temp;
}
Run Code Online (Sandbox Code Playgroud)
现在可以重写使用Optional:
public void setMemory(ArrayList<Integer> memory) {
this.memory = Optional.ofNullable(memory)
.map(ArrayList::new)
.filter(list -> ! list.contains(null))
.orElseThrow(() -> new IllegalArgumentException("memory is or contains null"));
}
Run Code Online (Sandbox Code Playgroud)
与通常的滥用相比:-) Optional我经常看到,这个并不算太糟糕.这里的链接用于避免创建局部变量,这有点胜利.逻辑是相当简单的,特别是如果一个人Optional在前脑上.但是,我有点担心在一个月内重新访问这段代码.你可能不得不眯着眼睛看一下,然后说服自己做了你打算做的事情.
最后,一对一般的风格评论.
通常的偏好(至少在JDK中)是NullPointerException用于这些情况.我坚持使用IllegalArgumentException这些例子,因为那是OP正在使用的.
我建议使用List<Integer>而不是ArrayList<Integer>参数类型和可能的字段类型.这将允许在适当的情况下使用不可修改的列表(例如,使用JDK 9 List.of).
| 归档时间: |
|
| 查看次数: |
3399 次 |
| 最近记录: |