简体   繁体   English

同时使用@Nonnull和Preconditions.checkNotNull(…)

[英]Using both @Nonnull and Preconditions.checkNotNull(…)

Does it make sense to have a parameter annotated with @Nonnull and later check the same with Preconditions.checkNotNull() ? 使用@Nonnull注释参数并随后使用Preconditions.checkNotNull()检查是否有意义?

What is the difference between them? 它们之间有什么区别? As far as I understand, using @Nonnull will just specify a contract but will not check further unless you tell it so in your IDE. 据我了解,使用@Nonnull只会指定一个合同,而不会进一步检查,除非您在IDE中进行了说明。 Is this correct? 这个对吗?

The difference is between specification and implementation. 规格和实现之间的区别。 @NonNull gives the specification of the routine, and Preconditions.checkNotNull() gives one way to validate the routine. @NonNull提供了例程的规范,而Preconditions.checkNotNull()提供了一种验证例程的方法。

@NonNull specifies a contract on a formal parameter: the method should never be called with null as the corresponding actual argument. @NonNull在形式参数上指定一个合同:永远不要使用null作为相应的实际参数来调用该方法。

There are multiple ways to validate such a specification. 有多种方法可以验证这种规范。

  • You can perform run-time checking with an assert statement or, equivalently, Preconditions.checkNotNull() . 您可以使用assert语句或等效地Preconditions.checkNotNull()进行运行时检查。 This will dynamically find violations of the contract at run time, and crash the program. 这将在运行时动态发现违反合同的情况,并使程序崩溃。 This makes your code easier to debug by giving an earlier warning message, but it doesn't improve code quality. 通过发出较早的警告消息,可以使您的代码更易于调试,但是并不能提高代码质量。

  • You can perform static checking at compile time using an IDE or other tool. 您可以在编译时使用IDE或其他工具执行静态检查。 If you use a sound tool, you get a guarantee that no possible execution will violate the specification and crash the program. 如果您使用声音工具,则可以确保不会执行任何违反规范的操作并使程序崩溃。

You need a specification of your method to document how it is supposed to be used. 您需要对方法进行规范以记录应如何使用。 You might as well write that using @NonNull annotations rather than in English as Javadoc, because @NonNull is concise and machine-readable. 您最好使用@NonNull注释而不是像Javadoc那样用英语编写,因为@NonNull简洁且可机读。 So, you should write @NonNull annotations. 因此,您应该编写@NonNull批注。

It's optional, but useful, to validate the correctness of your specification. 它是可选的,但很有用,可用来验证规范的正确性。 Doing validation using both run-time checking and static checking is a belt-and-suspenders approach. 同时使用运行时检查和静态检查进行验证是一种束手无策的方法。 It uses two different techniques to validate the specification. 它使用两种不同的技术来验证规范。 Doing run-time checking is a good idea if you use an unsound static checking tool such as FindBugs, since even if FindBugs doesn't issue any warnings, there still might be nullness errors in your code. 如果您使用不可靠的静态检查工具(例如FindBugs),则进行运行时检查是个好主意,因为即使FindBugs不会发出任何警告,您的代码中仍然可能存在空错误。 If you use a sound tool such as the Nullness Checker of the Checker Framework , then the run-time checks are extraneous. 如果使用声音工具(如Checker FrameworkNullness Checker) ,则运行时检查是多余的。 They don't hurt much, though: just a little bit of code clutter and a little bit of run-time overhead. 但是,它们并没有带来太大的伤害:只是一点点的代码混乱和一点点的运行时开销。

(Note that it is possible for the specification to require a particular exception to be thrown if a null value is passed as an argument. This would require the method body to contain code such as Preconditions.checkNotNull() even if you have already proved that your program never passes null. A specification that dictates the exact exception thrown isn't particularly useful to client code. The client really only wants to know in which circumstances the call will succeed, and the client is unlikely to have a catch block specifically for NullPointerException . Thus, the main information the client needs in the specification is that null is an illegal value.) (请注意,如果将空值作为参数传递,规范可能要求抛出特定异常。这将要求方法主体包含诸如Preconditions.checkNotNull()代码,即使您已经证明您的程序永远不会传递null。指示确切抛出异常的规范对客户端代码不是特别有用。客户端只想知道在哪种情况下调用将成功,并且客户端不太可能具有专门用于catchNullPointerException 。因此,客户端在规范中需要的主要信息是null是非法值。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM