【问题标题】:In Java, is it possible to declare a field that can never become null?在Java中,是否可以声明一个永远不会为空的字段?
【发布时间】:2020-06-02 18:01:56
【问题描述】:

假设我们定义了这个 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;
  }

}

这可以防止创建 isbn 为 null 的 Book 对象,但在创建具有非 null isbn 的 book 对象后,我们可以通过反射修改该值并将其设置为 null。

是否有任何方法(使用技巧或 Java 功能)来防止 Book 的实例永远存在于其 isbn 为空的内存中?

注意:这个问题与Optionals 无关。

【问题讨论】:

  • 另一个关门了,这个还活着。
  • 只需将其设为final,并在构造函数中指定this.isbn = Objects.requireNonNull(isbn)。编辑:从头开始,错过反射是一种选择
  • 如果您使用的是 Kotlin,这会容易得多。我想用@NotNull 警告其他人是你能得到的最接近的(没有制作编译器插件)
  • 不在兼容的 JVM 中。引用可以为空。
  • 由于您的类不可序列化,因此使该字段为空的唯一方法是通过反射。您可以使用SecurityManager 防止这种情况发生。例如,扩展 SecurityManager 类,您可以在应用程序级别使用反射来拒绝

标签: java null


【解决方案1】:

技术上的引用是可以为空的。即使您可以使用final 来确保编译器不会让您留下变量null,您也可以使用反射来移除其最终确定性并将其设置为null。

如果您不考虑反射,那么我们可以说本机代码或Unsafe 或字节码检测等等。最后,内部表示允许空值,因此取决于您将走多远,如果您真的想要,将有一种方法可以创建变量null,除非您指定关于的约束允许/可能的情况,例如是否涉及SecurityManager

如果您之所以问这个问题是因为您担心您的变量对NullPointerExceptions 不够安全,那么使用finalObjects.requireNonNull() 和良好的设计就足够了。

【讨论】:

    【解决方案2】:

    如果要排除反射,答案是否定的。

    您唯一的选择是安装一个不允许反射的安全管理器,但您希望您的代码在哪个恶劣环境中运行?即使这样,启动 VM 的用户也可以添加一个代理,该代理可以操作字节码。

    所以,就总体安全而言:没有。

    【讨论】:

      猜你喜欢
      • 2021-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 1970-01-01
      • 2011-06-19
      • 1970-01-01
      相关资源
      最近更新 更多