假设我们定义了这个 Book 类,我们确保永远不会为 isbn 分配空值:
public class Book {
private String isbn;
public Book(String isbn) {
setIsbn(isbn);
}
public void setIsbn(String isbn) {
if (isbn == null) {
throw new NullPointerException();
}
this.isbn = isbn;
}
public String getIsbn() {
return this.isbn;
}
}
Run Code Online (Sandbox Code Playgroud)
这可以防止创建 isbn 为 null 的 Book 对象,但是在创建具有非 null isbn 的 book 对象之后,我们可以通过反射修改该值并将其设置为 null。
无论如何(使用技巧或Java功能)是否可以防止Book的实例存在于其isbn为空的内存中?
注意:这个问题与Optionals无关。
从技术上讲,引用是可以为空的。即使您可以使用final来确保编译器不会让您留下变量null,您也可以使用反射来删除其最终性并将其设置为 null。
如果你算上反射,那么让我们说原生代码Unsafe或字节码检测等等。最后,内部表示允许空值,所以根据你要走多远,null如果你真的想要的话,会有一种方法来创建一个变量,除非你指定关于允许/可能的约束,例如 a 是否SecurityManager是涉及。
如果你问这个问题,因为你害怕,你的变量不是足够安全距离NullPointerExceptions,然后利用final,Objects.requireNonNull()以及良好的设计是不够的。
如果要排除反射,答案是否定的。
您唯一的选择是安装一个不允许反射的安全管理器,但是您希望您的代码在哪个敌对环境中运行?即便如此,启动 VM 的用户也可以添加一个代理,该代理可以操作字节码。
因此,就总体安全而言:不。