看看java.util.OptionalInt
的源代码,一个可选的int由int value
和boolean isPresent
组成。获取空的可选int的唯一方法是通过OptionalInt.empty()
方法,该方法返回OptionalInt.EMPTY
,这是所有空的可选int的公共实例。
如果是这种情况,那么为什么将isPresent()
方法实现为return isPresent
而不是this == EMPTY
并通过摆脱isPresent
字段来减少内存使用? / p>
答案 0 :(得分:4)
这是实现的选择,唯一能给出明确答案的人就是编写实现的人。
但是很可能是这样一种选择,它使代码的可读性,清晰度和可维护性超过了内存微优化。
担心布尔值在包装int的对象中占用的空间确实没有多大意义。如果该空间是相关的,则考虑对象标头至少需要8个字节(在32位JVM上,至少在64位上),因此不应首先使用OptionalInt
(或Java)。已经。
Java并非用于编写受内存限制的应用程序,而是用于编写易于维护的代码。将isPresent()
用作isPresent
的吸气剂,更易于阅读,重构时出错更少,并且符合既定的Java编码惯例。
附带说明:由于Java对象是8字节对齐的,因此在删除 正如Eugene在评论中指出的那样,实际上确实增加了大小,因为字段isPresent
时,它甚至可能不会使类变小。 isPresent
恰好位于边界上,然后又添加了7个字节用于填充。
答案 1 :(得分:3)
如OptionalInt.empty()
方法的文档中所述:
尽管这样做可能很诱人,但请避免测试对象是否为空 通过与
==
返回的实例与OptionalInt.empty()
进行比较。 不能保证它是一个单例。而是使用#isPresent()
。
事实上,以下测试已通过:
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
import java.lang.reflect.InvocationTargetException;
import java.util.OptionalInt;
import org.junit.jupiter.api.Test;
class Tests {
@Test
void test() {
var empty = OptionalInt.empty();
assertSame(empty, empty);
var anotherEmpty = fabricateEmpty();
assertFalse(anotherEmpty.isPresent());
assertNotSame(empty, anotherEmpty);
}
private OptionalInt fabricateEmpty() {
try {
var constructor = OptionalInt.class.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
} catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
尽管看起来有些人为,但许多流行的框架还是使用反射或Unsafe
来构造实例。