返回 NULL 的替代方案

发布于 2024-11-07 04:28:28 字数 659 浏览 0 评论 0原文

   /**
     * Returns the foo with the matching id in this list
     * 
     * @param id the id of the foo to return
     * @return the foo with the matching id in this list
     */
    public Foo getFoo(int id)
    {
        for (Foo foo : list)
        {
            if (foo.getID() == id)
            {
                return foo;
            }
        }

        return null;
    }

当找不到 foo 时,我应该抛出一个异常,而不是返回null吗?这重要吗?关于这个主题是否有“最佳实践”习语?顺便说一句,我知道我的例子有点做作,但我希望你明白......

谢谢。

编辑

更改了代码以根据id获取Foo,以更好地说明现实世界的场景。

   /**
     * Returns the foo with the matching id in this list
     * 
     * @param id the id of the foo to return
     * @return the foo with the matching id in this list
     */
    public Foo getFoo(int id)
    {
        for (Foo foo : list)
        {
            if (foo.getID() == id)
            {
                return foo;
            }
        }

        return null;
    }

Instead of returning null when foo is not found, should I throw an exception? Does it matter, and is there a "best practices" idiom on the subject? By the way, I know my example is a bit contrived, but I hope you get the idea...

Thanks.

EDIT

Changed code to get Foo based on id to better illustrate a real-world scenario.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

羅雙樹 2024-11-14 04:28:28

返回 null 不仅处理起来更简单,而且性能也更好。必须使用异常来处理异常情况。

Returning null is not only more simple to handle, performs better too. The exceptions must be used to handle exceptional cases.

梦屿孤独相伴 2024-11-14 04:28:28

我想说这取决于你的方法的语义。

foo 几乎总能在列表中找到吗? (例如,如果它是保存有限数量对象的缓存)。如果是这样,那么找不到可能意味着出现了问题 - 例如,某些应用程序初始化失败,或者密钥无效 - 并且异常可能是合理的。

然而,在大多数情况下,我会返回 null。也许客户端知道该对象可能不存在并且具有编码逻辑来处理这种情况;如果您使用异常,该代码将更难以阅读、理解和维护。

一些 API 实际上提供了两种方法:可能返回 null 的 find 方法,以及引发异常的 getload 方法。

嗯...如有疑问,请错误地支持 null :)

I'd say it depends on the semantics of your method.

Will foo be almost always found in the list? (for example, if it is a cache that holds a finite amount of objects). If so, then not being found might mean something has gone wrong -- some app initialization failed, for example, or the key is invalid -- and an exception might be justifiable.

In most circumstances, however, I'd return null. Maybe the client knows the object might not be there and has coded logic to handle that case; if you used an exception, that code would be much harder to read, understand, and maintain.

Some APIs actually provide two methods: a find method that may return null, and a get or load method that throws an exception.

Hmmm... when in doubt, err in favor of null :)

夜还是长夜 2024-11-14 04:28:28

如果它被记录为有效结果,则返回 null 就可以了。

另一种选择是空对象模式。也就是说 - 一个没有任何数据的 Foo 实例:

public class Foo {
    public static final Foo NULL_FOO = new Foo();
}

并返回它。

Returning null is fine, if it is documented as a valid result.

Another option is the null-object pattern. That is - an instance of Foo that doesn't have any data:

public class Foo {
    public static final Foo NULL_FOO = new Foo();
}

and return it instead.

叹沉浮 2024-11-14 04:28:28

我更喜欢返回 null。这是从方法返回的完美结果,并且调用该方法的代码应该适当地处理 null 值。这可能意味着在调用代码中抛出异常,但我不会在这个方法中这样做。

这样,如果其他人想要调用您的方法,他们可以选择以与您不同的方式处理空值。如果你抛出异常,它可能会迫使另一个程序员以不同于他们预期的方式更改他们的代码。

当然,在某些情况下,如果某些内容为空(例如,连接对象或类似的东西,您实际上需要有一个值,那么抛出异常是有意义的,如果没有,则意味着某些内容是空的)错误的)。但是,根据经验,在大多数情况下返回 null 应该没问题。

I prefer returning null. This is a perfectly fine result to return from a method, and your code that calls the method should handle null values appropriately. That might mean throwing an exception in your calling code, but I wouldn't do it in this method.

This way, if someone else wants to call your method down the line, they can handle null values differently than you if they choose. If you threw and exception it could potentially force another programmer to alter their code in a way different than what they intended.

Of course, there are some cases where it would make sense to throw an exception if something is null (like, a connection object or something like that, that you actually need to have a value and if you don't then that means something is wrong). But, as a rule of thumb, you should be fine returning null in most cases.

寂寞清仓 2024-11-14 04:28:28

如果可以的话最好避免异常,但有时你就是做不到。在这种情况下,如果您在列表中存储了 null 会怎样?您无法区分“找到空值”和“找不到您想要的内容”之间的区别。

有一种模式,称为选项类型,它在 Scala 中被大量使用。您要么返回一个包含该项目的容器,要么返回一个表示“我是空的”的类的容器。维基文章将提供更好的图片。

您还可以询问“该集合中是否存在此内容?”返回 bool 的方法,如果您没有先检查,则从上面的代码中抛出异常。


只是一条与您的实际问题完全无关的评论。如果您实现 equals,则仅当两个对象实际上被视为相等时才应返回 true。因此,上面的代码必须始终返回您传递给它的对象!

It's best to avoid exceptions if you can, but sometimes you just can't. In this case, what if you had stored null in the list? You can't tell the difference between 'found null' and 'could not find what you wanted'.

There is a pattern, it's called Option Types and it's used a lot in Scala. You either return a container with the item, or a container of a class that says 'I'm empty'. The wiki article will give a better picture.

You could also have a 'does this exist in the collection?' method which returns a bool, then throw an exception from the above code for if you didn't check first.


And just a comment completely unrelated to your actual question. If you implement equals, it should only return true if the two objects are actually considered equal. Therefore the above code must always return the object you pass into it!

一场信仰旅途 2024-11-14 04:28:28

最好的做法是在 Javadoc 中声明,当未找到匹配项时,将返回 null

另一种方法可能是返回一个可能为空(并且可能有多个)的匹配列表,但是我不喜欢这种方法。

另一种方法可能是返回 Foo 类型值的 NULL_FOO。

我宁愿只返回 null。

解决这个问题的一种方法是查看您将如何处理该值并丰富函数,以便返回的值在方法中使用而不是返回。例如,如果您要使用该值调用一个方法,只需在函数中调用它即可避免返回任何内容。

Best pactice would be to say in the Javadoc that null is return when no match is found.

Another approach might be to return a List of matches which could be empty (and could have more than one) However I don't like this approach.

Another approach might be to return a NULL_FOO of type Foo value.

I would prefer to just return null.

One way around this is to look at what are you going to do with the value and enrich the function so that the returned value is used in the method and not returned. e.g. if you are going to call a method with the value, just call it in the function which avoids the need to return anything.

青萝楚歌 2024-11-14 04:28:28

这是一个老问题,但我没有找到番石榴的 可选 类以及 JDK 的 可选(来自 Java 8),具有相同的目的并具有更多功能。

这篇文章很好地概述了使用 guava 的Optional 的原因。我强烈推荐阅读它。

这是摘录:

重点是什么?

除了通过赋予 null 来增加可读性之外
顾名思义,Optional 的最大优点是它的防白痴性。它
如果您想要
程序根本无法编译,因为您必须主动解开
可选并解决该情况。 Null 使得它变得非常容易
简单地忘记事情,虽然 FindBugs 有帮助,但我们不认为它有帮助
几乎也解决了这个问题。

当您返回的值可能或
可能不“存在”。你(和其他人)更有可能忘记
other.method(a, b) 可能会返回一个比您想象的空值
当你实现 other.method 时,忘记 a 可能为 null。
返回Optional使得调用者不可能忘记这一点
情况下,因为他们必须自己为代码解开对象
编译。

我个人的观点(如果这很重要的话)是,在像 Java 这样已经很冗长的语言中,返回 null 并不是那么可怕。该方法的签名有时会尖叫可能存在某种空类型的结果,并且使用Optional无论如何都不会在语义方面添加任何内容。例如:

public Point2D intersect(Line line)

或者在通过键在映射中查找值的方法中。

如果调用这样的方法并对结果执行空检查,则很明显发生了什么(检查平行线或未找到键)。我倾向于返回 null 以免代码膨胀。

不过我总是会在 javadoc 中记录它。

This is an old question but I didn't find guava's Optional class mentioned here and also JDK's Optional (from Java 8) which serves the same purpose and has more functionality.

This article is a good overview on the reasons for using guava's Optional. I highly recommend reading it.

Here's an excerpt:

What's the point?

Besides the increase in readability that comes from giving null a
name, the biggest advantage of Optional is its idiot-proof-ness. It
forces you to actively think about the absent case if you want your
program to compile at all, since you have to actively unwrap the
Optional and address that case. Null makes it disturbingly easy to
simply forget things, and though FindBugs helps, we don't think it
addresses the issue nearly as well.

This is especially relevant when you're returning values that may or
may not be "present." You (and others) are far more likely to forget
that other.method(a, b) could return a null value than you're likely
to forget that a could be null when you're implementing other.method.
Returning Optional makes it impossible for callers to forget that
case, since they have to unwrap the object themselves for their code
to compile.

My personal opinion, if that matters at all, is that returning null is not so terrible in an already verbose language like Java. The signature of the method sometimes screams that there can be some sort of null kind of result and using Optional doesn't add anything in terms of semantics anyway. For example:

public Point2D intersect(Line line)

Or in a method that looks up a value in a map by key.

If one calls such a method and performs a null check on the result, it's pretty obvious what is going on (checking for parallel lines or key not found). I would favor returning null lest I bloat my code.

I would always document it in the javadoc though.

暖树树初阳… 2024-11-14 04:28:28

主要取决于场景。如果您的应用程序本身就是该方法的生产者和使用者,那么完全由您决定要做什么,否则您需要根据该方法的使用情况和客户需求来决定。

majory it depends on the scenarios. If your app is itself producer and consumer of this method then it is completly upto you to decide what to do, Else you need to decide based on usage of the method and Client needs.

吃颗糖壮壮胆 2024-11-14 04:28:28

返回 null 是完全可以接受的。我会进行额外的几十次击键,并在 JavaDoc 中记录返回 null 的可能性。

抛出已检查的异常意味着您必须在调用方法的任何地方尝试/捕获或重新抛出该异常。未经检查的异常,尤其是 NPE 以外的任何异常,都会让人们大吃一惊。

Returning null is perfectly acceptable. I would go the extra couple dozen keystrokes and document the possibility of returning null in the JavaDoc.

Throwing checked exception means you have to try/catch or re-throw that exception everywhere your method gets called. An unchecked exception, especially anything other than an NPE, is going to catch people by surprise.

蓝天白云 2024-11-14 04:28:28

在本例中,由于您正在定义一个访问器,因此它应该返回 null。如果是另一种方法,该方法应保证非空响应,则异常会更合适。

不过,作为旁注,与其将示例方法称为 getter,不如将其命名为 Foo findFoo(Foo f) 之类的名称,因为您正在搜索而不仅仅是获取。

In this case, since you're defining an accessor, it should return null. If it were another method where this method should guarantee a non-null response, an exception would be more appropriate.

As a side note though, rather than calling the sample method a getter it might be more appropriate to name it something like Foo findFoo(Foo f) since you're searching rather than just getting.

夏尔 2024-11-14 04:28:28

我认为这是一个品味问题,在这种情况下,它还取决于列表是否可能包含空值。如果列表可能包含 null 值,则 null 也将是有效的方法参数,并且您需要区分返回 null(例如传递、找到并返回 null)或告诉方法调用者传递的 null 值不是空值发现。

I think it's a matter of taste and in this case it also depends on if the list may contain null values. If the list may contain null values, null would also be a valid method argument and you would need to distinguish between returning null (e.g. null was passed, found and returned) or telling the method caller that the passed null value was not found.

愛上了 2024-11-14 04:28:28

这可能不会直接回答你的问题,但它来自我从 Stackoverflow 成员那里得到的关于类似主题的一些评论。

当未找到 foo 时,我应该抛出异常,而不是返回 null 吗?这重要吗?关于这个主题是否有“最佳实践”习语?顺便说一句,我知道我的例子有点做作,但我希望你能明白......”

根据我的收集,当异常涉及给定方法的参数时,应该从方法中抛出异常。例如,接受 File 实例的方法将抛出 NullPointerException 或 IOException ,这遵循调用者和被调用者之间存在契约的想法,调用者应该发送有效的对象并在它们无效时处理它们

。决定是否处理前置条件和后置条件。您可以在方法的开头放置一个保护来处理参数,这会节省大量代码,但是,有些人认为这是一种不正确的方法,例如在验证中。 UI,应该提前完成

,如果意图是检索单个实例,那么返回一个空对象是完全有效的,这意味着当涉及到组时,没有找到或不存在对象。我认为约定只是返回一个空的集合/列表。

This might not answer your question directly but it comes from a few remarks I've gotten from Stackoverflow members on similar topics.

Instead of returning null when foo is not found, should I throw an exception? Does it matter, and is there a "best practices" idiom on the subject? By the way, I know my example is a bit contrived, but I hope you get the idea..."

From what I gather, Exceptions should be thrown from a method when the Exception concerns a parameter given to the method. For example, a method accepting File instances would throw a NullPointerException or an IOException. This is following the idea that there's a contract between the caller and callee that the caller should sent valid objects and take care of them if they're invalid.

Also, you need to decide whether to handle pre- and postconditions. You can place a guard at the beginning of a method to handle parameters and this would save quite a bit of code. However, some view this as an incorrect approach in that some validation, say in a UI, should be done beforehand.

To finish off, it's perfectly valid to return a null object if the intent is to retrieve a a single instance. This is to paraphrase that an object was not found or doesn't exist. When it comes to groups of objects I think the convention is simply to return an empty Collection/List.

又爬满兰若 2024-11-14 04:28:28

我想说这取决于您的应用程序以及如何使用该方法。

  1. 如果您预计“未找到”结果发生的频率足够高,可能会对性能*产生负面影响,则返回 null,并在调用方中检查它。
  2. 如果“未找到”结果相对罕见,或者会导致您的应用程序放弃请求,那么抛出异常就可以了。异常可以使您的代码更易于阅读,因为您可以保证成功返回将生成一个对象,因此您不必对其进行空检查。

我同意这样的观点:异常应该用于异常条件,这是错误条件的超集。我还采用了 Spring/Hibernate 对未检查异常的偏好,这避免了繁琐的 try/catch 逻辑。

* 使用异常与返回 null 相比并没有太多性能开销。我刚刚做了一个快速测试,调用一个方法一百万次返回 null 需要 4ms,而调用另一个方法一百万次抛出异常只需要 535ms。

I'd say it depends on your app and how the method will be used.

  1. If you expect a "not found" result happen frequently enough that it could negatively affect performance*, then return null, and check for it in the caller.
  2. If "not found" results will be relatively rare or will cause you app give up on the request, then throwing an exception would be fine. Exceptions could make your code easier to read, as you can then guarantee a successful return will produce an object, so you don't have to null-check it.

I subscribe to the opinion that exceptions should be used for exceptional conditions, which is a superset of error conditions. I also have adopted Spring/Hibernate's preference for unchecked exceptions, which avoids burdensome try/catch logic.

* There is not much performance overhead from using exceptions vs. returning null. I just did a quick test, it takes 4ms to call a method a million times that returns null, and only 535ms to another method million times that throws an exception.

紧拥背影 2024-11-14 04:28:28

我在其他答案中没有读到的另一个观点如下:

list 是否包含 Foonull ?如果是这种情况,人们将不知道是否找到了该 id,或者它是否与 null 关联。在这种情况下:

  • 抛出列表未找到的异常;
  • 将结果包装在另一个对象中(例如 SearchResult,它告诉您是否找到该对象、它的关联 ID、它的结果,或者如果未找到则没有结果);
  • 创建方法 existsFoo(int id)

每个解决方案都有其自身的问题,具体取决于使用的情况:

  • 正如其他人指出的,Exception异常
  • 每次您想重试搜索时,都必须分配一个包装器 SearchResult。包装器可以变得可变,但这会带来很多新的困难和问题;
  • existsFoo 必须搜索列表,这使得了解键是否存在的成本增加了一倍。

一般来说,我可以说:

  • 未找到 ID 是否异常?使用IllegalArgumentException;
  • 结果是否传递给其他类,用作对象?使用包装器,例如 SearchResult
  • getFoo 是否只检查它是否为空(存在或不存在)?使用另一种方法,existsFoo

Another point of view I haven't read in the other answers is the following:

Does the list contain null's of Foo? If this is the case, one would not know whether the id was found, or whether it was associated with null. In this case:

  • Throw an exception that the list is not found;
  • Wrap the result in another object (e.g. a SearchResult, which tells you if the object was found, it's associative id, it's result, or no result if it was not found);
  • Create the method existsFoo(int id).

Each solution has it's own problems, and it depends on the case which to use:

  • As others noted, Exceptions are exceptional;
  • A wrapper, SearchResult, has to be allocated each time you'd like to retry a search. The wrapper can be made mutable, but this introduces a lot of new difficulties and problems;
  • existsFoo has to search the list which doubles the cost of knowing whether the key exists or not.

Generally I can say:

  • Is an ID not being found exceptional? Use IllegalArgumentException;
  • Is the result passed to other classes, used as an object? Use a wrapper, e.g. SearchResult;
  • Is with getFoo only checked whether it's null or not (it exists or not)? Use another method, existsFoo.
你是暖光i 2024-11-14 04:28:28

虽然我同意 null 编码是简单且容易的样板程序员调节,但它对于引入的复杂性几乎没有增加任何价值。始终假设非空引用可以使逻辑更清晰,代码稍微少一些——您仍然必须测试失败。

下面摘录的注释将帮助您避免陷入旧的方式。 ..

使用@Nullable

要消除代码库中的 NullPointerExceptions,您必须
对空引用进行纪律处分。我们在这方面取得了成功
遵循并执行一个简单的规则:

除非明确指定,否则每个参数都是非空的。

Guava:适用于 Java 和 JSR-305 的 Google 核心库具有简单的 API
控制空值。可以使用Preconditions.checkNotNull
如果发现空引用则快速失败,并且可以使用@Nullable
注释允许空值的参数:

导入静态com.google.common.base.Preconditions.checkNotNull;
导入静态 javax.annotation.Nullable;

公共类人{
  ...

  公共人(字符串名字,字符串姓氏,@Nullable Phone电话){
    this.firstName = checkNotNull(firstName, "firstName");
    this.lastName = checkNotNull(lastName, "lastName");
    this.phone = 电话;
  }

如果您的类允许 null,您可以注释该字段或
带有 @Nullable 的参数...使用任何 @Nullable 注释,例如
edu.umd.cs.findbugs.annotations.Nullable 或 javax.annotation.Nullable。

While I agree that coding for null is simple and easy boilerplate programmer conditioning, it adds little value for the complexity introduced. Always assuming non-null references makes for cleaner logic with slightly less code -- you still have to test for failure.

The annotation excerpt below will help you to not fall into the old ways...

Use @Nullable

To eliminate NullPointerExceptions in your codebase, you must be
disciplined about null references. We've been successful at this by
following and enforcing a simple rule:

Every parameter is non-null unless explicitly specified.

The Guava: Google Core Libraries for Java and JSR-305 have simple APIs
to get a nulls under control. Preconditions.checkNotNull can be used
to fast-fail if a null reference is found, and @Nullable can be used
to annotate a parameter that permits the null value:

import static com.google.common.base.Preconditions.checkNotNull;
import static javax.annotation.Nullable;

public class Person {
  ...

  public Person(String firstName, String lastName, @Nullable Phone phone) {
    this.firstName = checkNotNull(firstName, "firstName");
    this.lastName = checkNotNull(lastName, "lastName");
    this.phone = phone;
  }

If null is permissible by your class, you can annotate the field or
parameter with @Nullable ... using any @Nullable annotation, like
edu.umd.cs.findbugs.annotations.Nullable or javax.annotation.Nullable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文