【问题标题】:Is there a standard Java NonNullable<T> generic, and if not, why not?是否有标准的 Java NonNullable<T> 泛型,如果没有,为什么不呢?
【发布时间】:2011-09-19 15:02:41
【问题描述】:

@NotNull/@NonNull 等注解的问题在于它们在运行时没有被强制执行。我想做如下的事情:

class Foo {
  String nullable_string;
  final NonNullable<String> nn_string = new NonNullable<String>();
  ...
  public void mutate(String arg) {
    mutable_string = arg;  // arg could be null
    nn_string.set(arg);    // throws NullPointerException for me if arg is null.
  }
  ...
}

标准NonNullable&lt;T&gt; 泛型是否存在于某处,如果不存在,是否有理由认为这是一个坏主意?

【问题讨论】:

  • 您对这样的 NonNullable 泛型有何期望。它仍然在其核心中扩展 Object;并且每个 Object 都可以引用 null。无论 NonNullable 是如何构建的;我还可以NonNullable nn = null;
  • @Yhn: 这样一个类的重点不是确保NonNullable 类型的引用永远不会是null,而是确保它不包含null。也就是说,NonNullable 引用永远不应该是null,这可以通过将实例分配给示例中的final 字段来确保。
  • 查看 JSR 305 状态:stackoverflow.com/questions/2289694/…
  • 我主要使用import javax.annotation.xxx

标签: java generics null nullpointerexception non-nullable


【解决方案1】:

我很确定它不存在。但是您可以构建自己的:

public class NonNullable<T> {

    private T element;

    public void set(T element) {
        if (element == null)
            throw new NullPointerException("Parameter was null!");
        else
            this.element = element;
    }

}

【讨论】:

  • 自建绝对是我目前的方向。
【解决方案2】:

IntelliJ 有@NotNull and @Nullable annotations。它使用 IDE 中的静态检查和字节码检测在运行时执行检查。您还可以检测运行时检查。

【讨论】:

    【解决方案3】:

    没有必要为此使用特殊的包装类。如果您不想让某些东西成为null,请确保它不是null,当它通过支票提供给您时。您可以使用标准 Java 做到这一点:

    if (arg == null)
      throw new NullPointerException();
    this.string = arg;
    

    或者使用Guava,您可以使用Preconditions 类将其简化为:

    this.string = checkNotNull(arg); // using static import
    

    在 Guava 的 r10 中,不久之后就会出现,您还可以使用 Optional<T>(不可变)或 Holder<T>(可变)。这些不一定正是您要查找的内容,因为它们都被允许“不存在”(没有价值),但它们都不可能包含nullHolder 特别似乎适用于您的示例中的场景,因为您没有显示它被初始化为任何值(它在创建时没有给出任何 String,所以它最初必须不存在) .如果给定null,它的set 方法将抛出NullPointerException,就像你想要的那样。

    final Holder<String> stringHolder = Holder.absent(); // nothing at first
    
    public void mutate(String arg) {
      stringHolder.set(arg);
    }
    

    当使用HolderOptional 时,您通常应该在调用get() 之前检查它isPresent(),因为如果不存在它会抛出IllegalStateException。或者,您可以使用or 方法:

    String definitelyNotNull = stringHolder.or("default");
    

    【讨论】:

    • 如果不允许 null,你应该抛出 IllegalArgumentException 而不是 NullPointerException。由于这是一个非法参数,IllegalArgumentException 是适当的例外。
    • @Steve:对此有两个阵营,但我所知道的 Java 程序员的普遍共识是,NullPointerException 是当参数为 null 时应该抛出的,因为它更多这种情况下的特定例外。
    • 是的,看起来 IllegalArgumentExceptionNullPointerException 的争论很激烈 stackoverflow.com/questions/3881/…
    • 包装类可防止您写出的 arg 检查中隐含的代码重复,并确保如果在类实现中的多个位置设置了值,则任何 null 都会被捕获。 Holder 看起来是正确的概念,但我们没有使用 Guava。你是对的,“缺席”显然是一个概念,如果可以在没有参数的情况下创建 NonNullable ,它就必须起作用。
    • @ColinD,你是认真的吗?在接口中指定非空值将是有益的 - 因此,在调用函数之前,在创建参数时已经强制执行检查。早点失败?不强制执行注释(在编译时很难确定可空性),并且我们不想在函数体中重复代码。对我来说,这种需求似乎非常很明显。我很惊讶java没有这样的类型。
    【解决方案4】:

    怎么样:

    NonNullable<?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      相关资源
      最近更新 更多