java-如何显示方法是否可以返回nu

在发布了这个问题并阅读了一个问题之后,我意识到知道一个方法是否应该返回null,或者是否将其视为错误条件并抛出异常非常重要。 当返回“ null”或引发异常时,也有很好的讨论。

我正在编写一个方法,并且我已经知道如果要返回null或引发异常,那么表达我的决定(换句话说,记录我的合同)的最佳方法是什么?

我可以想到的一些方法:

把它写在规格/文档中(有人读吗?)

使其成为方法名称的一部分(正如我在此处建议的那样)

假定所有引发异常的方法都不会返回null,而每个“不”引发的方法都可能返回null。

我主要是在谈论java,但是它也可能适用于其他语言:为什么有一种表达是否抛出异常的正式方法(Option关键字),却没有一种表达是否返回null的正式方法?

为什么没有这样的东西:

public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}

总结与结论

有很多表达合同的方式:

如果您的IDE支持(例如IntelliJ),则最好使用像Option这样的注释,因为它对于程序员是可见的,并且可以用于自动编译时间检查。 有一个Eclipse插件可以添加对这些插件的支持,但是对我来说不起作用。

如果不是这些选项,请使用自定义类型,例如Option或NotNull,这可以增加清晰度并至少可以进行运行时检查。

无论如何,在JavaDoc中记录合同永远不会受到伤害,有时甚至会有所帮助。

除了我之外,没有人提议使用方法名称来记录返回值的可为空性,尽管它可能很冗长而且并不总是有用,但我仍然相信有时它也有其优点。

11个解决方案

36 votes

一个很好的跟进问题。 我认为null是一个真正的特殊值,如果某个方法可以返回null,则该方法必须在Javadoc中清楚地记录该文档(@return some value ..., or null if ...)。 编码时我很防御,并假设除非我确信方法不能返回null(例如,因为Javadoc这样说),否则方法可能会返回null。

人们意识到这是一个问题,提出的解决方案是使用注释以一种可以自动检查意图的方式来陈述意图。 请参阅“ JSR 305:软件缺陷检测注释”,“ JSR 308:Java类型注释和JetBrain的Nullable How-To”。

您的示例可能看起来像这样,并被IDE,编译器或其他代码分析工具拒绝。

@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
Ronald Blaschke answered 2020-07-11T01:45:39Z
8 votes

您可以使用2961082236836864562176类型,该类型非常类似于具有零个或一个元素的列表。 返回类型Option表示该方法可能返回Object,或者可能返回类型None的特殊值。此类型替代了使用null并具有更好的类型检查的方法。

例:

public Option parseInt(String s) {
try {
return Option.some(Integer.parseInt(s));
}
catch (Exception e) {
return Option.none();
}
}

如果始终使用此选项,则可以打开IDE空警告,或者仅对Option使用grep,如果您在通常使用Iterable文字的任何地方都使用Maybe,则该代码根本不会出现在代码中。

Option是Scala的标准配置,在Haskell中称为Maybe。 上面的链接是一个包含它的名为Functional Java的库。 该版本实现了Iterable接口,并具有可让您很好地编写内容的单子方法。 例如,如果是2961082236881881339395,则提供默认值0:

int x = optionalInt.orSome(0);

您可以替换它...

if (myString != null && !"".equals(myString))

...如果您有Option ...

for (String s : myOptionString)

Apocalisp answered 2020-07-11T01:46:22Z

2 votes

确实:在我们的框架中,我们有一个“非空”指针类型,可以将其返回以指示该方法将始终返回值。

我看到三个选择:

等待语言支持来表达它(例如C#?!东西)

使用Aspect Orientation构建自己的语言扩展来表达它

使用自定义类型来表达它

(但建立在开发人员合作的基础上)使用命名方案来表示它

xtofl answered 2020-07-11T01:47:05Z

2 votes

对于Java,可以使用方法的Javadoc描述来记录返回值的含义,包括它是否可以为null。 如前所述,注释在这里也可以提供帮助。

另一方面,我承认我不认为null是值得担心的事情。 在某些情况下,“没人在家”是有意义的条件(尽管“空对象”技术在这里也具有实际价值)。

的确,尝试对null值进行方法调用将导致异常。 但是尝试除以零也是如此。 这并不意味着我们需要进行消除零的运动! 这仅意味着我们需要了解方法上的协定,并使用其返回的值进行正确的操作。

joel.neely answered 2020-07-11T01:47:35Z

1 votes

您看过Spec#吗?

Ray Booysen answered 2020-07-11T01:47:54Z

1 votes

您可以编写自己的注释(Java)或属性(C#)来指示返回值可能为null。 没有任何东西会自动检查它(尽管.NET 4.0将具有针对此类情况的代码契约),但它至少会充当文档。

Jon Skeet answered 2020-07-11T01:48:15Z

1 votes

IntelliJ IDEA中对@Nullable和@NotNull批注提供了一些支持。 也有一些关于将这些注释(或类似功能)添加到Java 7的讨论。不幸的是,我不知道它能走多远,或者它是否仍在前进。

Joachim Sauer answered 2020-07-11T01:48:35Z

1 votes

也许您可以定义一个名为“ NotNull”的通用类,这样您的方法可能类似于:

public NotNull methodWhichCannotReturnNull(int i) throws Exception
{
// the following would lead to a run-time error thown by the
// NotNull constructor, if it's constructed with a null value
return new NotNull(null);
}

这仍然是运行时(而不是编译时)检查,但是:

在方法的实现中抛出(这不是调用代码中的错误)

它是自记录文件(呼叫者知道他将NotNull作为返回类型)

ChrisW answered 2020-07-11T01:49:08Z

1 votes

不惜一切代价,避免依赖JavaDocs。 人们只会在签名看起来不琐碎且不言自明的情况下才阅读它们(一开始不好),而那些实际上为阅读它们而烦恼的人则不太可能会误认为空值,因为他们目前更加谨慎 。

Uri answered 2020-07-11T01:49:28Z

0 votes

如果您使用的是Java 5+,则可以使用自定义注释,例如 @MayReturnNull

更新

除了所有编码原理(使用异常,断言,yada yada返回null),我希望以上内容可以回答您的问题。 除了具有默认值的原语以外,复杂类型可能为null或不为null,并且您的代码需要处理它。

opyate answered 2020-07-11T01:49:57Z

0 votes

一般来说,我会假设默认情况下,空返回值违反了API的约定。 几乎总是可以将代码设计为在“正常”执行流程期间从API永不返回空值。 (例如,检查foo.contains(obj)而不是调用foo.get(obj)并为null设置一个单独的分支。或者,使用Null对象模式。

如果您无法以这种方式设计API,那么我会清楚地记录何时以及为什么会引发null -至少在Javadoc中,并且可能还会使用自定义@annotation,例如其他一些答案。

Ross answered 2020-07-11T01:50:23Z