我最近将JSR305的RI添加到我的项目中,并且一直在为我的界面添加注释:
public interface AccountService
{
@Nullable AccountResult consolidate( @Nonnull Date from, @Nonnull Date to )
}
根据JSR的精神(如此处所述),您认为我在界面中使用它们会误用注释吗?我想指出返回值可以为null但我认为@Nullable更多地应用于方法“合并”。我没有将它们添加到实现中,因为当我编码时,接口的代码是我的指路明灯。
答案 0 :(得分:6)
您可以将'@NonNull String'视为String的严格子类。毕竟,任何非null的String肯定是'instanceof''@ Nullable String',但是'@Nullable String'的任何实例都可能不是'@NonNull String'的实例(如果它不会是它例如, null。
以这种方式看,@ Nullable和@NonNull是类型信息,因此在接口中非常合理。您向实现者指出它们可能返回null,并且它们不必担心输入空值,并且您向调用者指示它们不能传入null,并且它们应该期望空值。
当然,虽然这一切都非常合理,但vanilla javac v1.6肯定不会强制实施任何这些规则,因为它强制实际类型的类型安全。但是人们可以梦想,或者可以使用像pmd或findbugs这样的东西来验证这些注释。
但是@NonNull和@Nullable注释对于完整的无效类型系统来说是不够的。我真的不知道为什么JSR305没有解决这个问题,但还有第三种类型:“@ MaybeNull”。它会显示在泛型参数内部;在任何其他地方,它与@Nullable具有相同的含义。
public static void addIfNotNull(List< @MaybeNull T> list,@ Nullable T item){ if(item!= null)list.add(item); }
如果第一个'T'上的注释有“@Nullable”,那么你就无法传入非空列表,这会产生一个相当无用的API。另一方面,如果它是@NonNull,你就无法传递一个可空的列表。在实践中,你在那里移动并不重要,它将(A)永远不会导致NullPointerException,并且(B)从不违反了注释。所以,你需要一种表达方式:我不在乎这个特定的'T'是否可以为空;我会在读取它时进行空值检查,并且我永远不会写空值,所以没关系。
@ MaybeNull和@Nullable之间的区别类似于'?在泛型中扩展Number'和'Number'。除了泛型之外,它们的意思相同,但在泛型中存在差异。
所以,不要让你的希望很快就会出现严格的类型检查。
@Inherited仅适用于类,但可以想象类似于带注释的返回类型和带注释的参数。
答案 1 :(得分:1)
我认为这取决于您添加注释的原因。
如果您只是添加它们以供参考,以便界面的实施者知道您的预期设计,那就没关系。
我使用注释进行事务处理和安全角色实施,因此我的注释处于实现级别。有趣的是,我的Spring容器中的AOP处理器可以测试这个或那个注释的存在,并应用适当的代理类来执行诸如定义事务边界或确保用户被授权进行某些特定方法调用。
因此,如果您计划关闭是否存在注释的任何处理,请确保您的实现已注释。如果仅供参考,可以只注释界面。