java 抛出异常或返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10873485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 02:56:02  来源:igfitidea点击:

Throw an exception or return null

javaexceptioncoding-stylenull

提问by Blundell

If I've got the function below, with two choices

如果我有下面的功能,有两个选择

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    return null;
}

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    throw new NoSuchFieldError("No blank piece found!");
}

From this method I know that it should always return an objectone of the 'pieces' always is isBlank() == true, the return null at the end is just to please the compiler. Since this is the case and my code wouldn't work anyway if it returned null, is this the correct please to throw an exception?

从这个方法我知道它应该总是返回一个对象,其中一个“部分”总是是isBlank() == true,最后返回 null 只是为了取悦编译器。既然是这种情况,而且如果它返回 null,我的代码无论如何都不会工作,这是抛出异常的正确方法吗?

My options are:

我的选择是:

  1. return null and the app will get a NullPointerException in some edge case
  2. return null and wrap the use of the method with (myObject != null) checks
  3. throw an exception which will blow it up at runtime
  1. 返回 null 并且应用程序将在某些边缘情况下获得 NullPointerException
  2. 返回 null 并使用 (myObject != null) 检查包装该方法的使用
  3. 抛出一个异常,它将在运行时炸毁它

I guess what I'm asking is, is this the correct place to throw an exception? i.e. there is nothing I can do about it if it gets into the situation. Is this classed as 'exceptional' or should I null check what my method returns (which makes my code look horrible). If I know it shouldn't return null then I should throw the exception right?

我想我要问的是,这是抛出异常的正确位置吗?即如果它陷入这种情况,我无能为力。这是被归类为“异常”还是我应该检查我的方法返回的内容(这使我的代码看起来很糟糕)。如果我知道它不应该返回 null 那么我应该抛出异常吗?

Also how would I choose what exception, or extend one and throw my own?

另外我将如何选择什么异常,或者扩展一个并抛出我自己的异常?

采纳答案by Wormbo

About your options, ask yourself if

关于你的选择,问问自己

  1. Is it a good idea to have your program blow up at some point after this method returned an unexpected value (i.e. null)?
  2. What exactly will be hidden if you mask out the nullreturn value?
  3. Is it a good idea to blow up immediately, just because there was a wrong value?
  1. 在此方法返回意外值(即null)之后的某个时候让您的程序崩溃是个好主意吗?
  2. 如果屏蔽null返回值,究竟会隐藏什么?
  3. 仅仅因为有错误的值就立即炸毁是个好主意吗?

Personally I'd go for option 2 or 3, depending on whether I like the answer to question 2 or 3 better. Option 1 definitely is a bad idea, especially if it's not supposed to happen. If the program throws a NPE way after your function returned, you'll have a hard time figuring out where the nullcame from. Especially if it happens months after you finished working on this particular function.

就我个人而言,我会选择选项 2 或 3,这取决于我更喜欢​​问题 2 还是问题 3 的答案。选项 1 绝对是个坏主意,尤其是在它不应该发生的情况下。如果程序在您的函数返回后抛出 NPE 方式,您将很难弄清楚它的null来源。特别是如果它发生在您完成此特定功能的几个月后。

If you choose to throw an exception, you immediately see wheresomething went wrong and you can directly go there to figure out whyit went wrong. Returning nulland checking for it in the calling function could also work, but only if you don't fail silently, but actually do something to handle the problem properly.

如果您选择抛出一个异常,您可以立即看到哪里出了问题,你可以直接去那里弄清楚为什么出了问题。null在调用函数中返回并检查它也可以工作,但前提是您没有静默失败,而是实际做一些事情来正确处理问题。

回答by K-ballo

I guess what I'm asking is, is this the correct place to throw an exception?

我想我要问的是,这是抛出异常的正确位置吗?

If it were an exceptionalsituation, then yes. If the possibility of not finding anything that matches the criteria is expectedthen the situation is not exceptionaland you should return null.

如果是特殊情况,那么是的。如果预计可能找不到符合条件的任何内容,则情况并非异常,您应该返回null

回答by Paul Bellora

Yes, you should throw a RuntimeExceptionto indicate an "exceptional" situation that should not have occurred. IllegalStateExceptionprobably fits the bill. Make sure to include a message with any information that will help you find the bug if it is ever thrown.

是的,您应该抛出 aRuntimeException来指示不应该发生的“异常”情况。IllegalStateException可能符合要求。确保包含一条消息,其中包含任何信息,如果它被抛出,将帮助您找到错误。

回答by prime

May be it's a good idea to use Null Object pattern.

使用空对象模式可能是个好主意。

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

So in that case you won't have to use exceptions or return null. You can always return the intended return type object. The trick is when you have nothing to return , instead of returning nullor throwing an exception you can return the Null objectwhich is the same type as intended return type.

因此,在这种情况下,您不必使用异常或返回 null。您始终可以返回预期的返回类型对象。诀窍是当您没有什么可返回时,null您可以返回与Null object预期返回类型相同的类型,而不是返回或抛出异常。

This documentationhas some examples and descriptions. And has a similar case as you, solved by the design pattern.

文档有一些示例和说明。和你有类似的情况,通过设计模式解决。

public class CustomerFactory {

  public static final String[] names = {"Rob", "Joe", "Julie"};

  public static AbstractCustomer getCustomer(String name){   
    for (int i = 0; i < names.length; i++) {
       if (names[i].equalsIgnoreCase(name)){
         return new RealCustomer(name);
       }
    }
    return new NullCustomer();
  }
}

回答by Anand Undavia

Apart from most of the answers I would like to point out that if performanceis your concern then, Exceptions are way slower than returning null

除了大多数答案之外,我想指出的是,如果性能是您关注的问题,则异常比返回 null 慢得多

Take a look at this code:

看看这段代码:

class Main {
    public static void main(String[] args) {
        testException();
        testNull();
    }

    public static void testException() {
        long st = System.currentTimeMillis();
        for(int i=0;i<10000000;i++) {
            try{
                exp();
            } catch(Exception e) {

            }
        }
        long et = System.currentTimeMillis();
        System.out.println("Time taken with exceptions : "+(et-st));
    }

    public static void testNull() {
        long st = System.currentTimeMillis();
        for(int i=0;i<10000000;i++) {
            returnNull();
        }
        long et = System.currentTimeMillis();
        System.out.println("Time taken with null : "+(et-st));
    }

    public static void exp() throws Exception {
        throw new Exception();
    }

    public static Object returnNull() {
        return null;
    }
}

The results on my machine are :

我机器上的结果是:

Time taken with exceptions : 7526
Time taken with exceptions : 5

If the throwing exception is a rare condition in your code and won't happen frequently then the time taken in both the situations is almost same.

如果抛出异常在您的代码中是一种罕见的情况并且不会经常发生,那么在这两种情况下所花费的时间几乎相同。

You will have to make Performance vs Maintainability / Readabilitytrade off.

您将不得不在性能与可维护性/可读性之间进行权衡。

Read more about it here

在此处阅读更多相关信息

回答by Justin

Return null most of time will draw to the information lost from contract view, the consumer can not know what is the reason for the wrong response if get the null from producer.

Return null 大部分时候会借鉴contract view丢失的信息,如果从生产者那里得到null,消费者无法知道错误响应的原因是什么。

Looking your first code, there is two situation the outer code get the NULLPointerException: 1. The pieces is null 2. The pieces did not have such element

查看您的第一个代码,外部代码有两种情况会得到 NULLPointerException: 1. 碎片为空 2. 碎片没有这样的元素

So return null will mis-lead the outer code for further operation, it will draw potential problem.

所以 return null 会误导外部代码进行进一步的操作,会引出潜在的问题。

And talk about difference between return nullObject (not null) and exception, the major difference is PROBABILITY, that means: 1. If the empty situation is on much more probability, it should return nullObject so that ALL outer code can/should handle them explicitly. 2. If the empty situation is less probability, why not throw the exception so that final call function can handle it directly.

并讨论返回 nullObject(非 null)和异常之间的区别,主要区别在于 PROBABILITY,这意味着: 1. 如果空情况的概率更高,则应返回 nullObject,以便所有外部代码都可以/应该显式处理它们. 2.如果空的情况概率较小,为什么不抛出异常,让最终调用函数可以直接处理。

回答by AgilePro

I believe the correct answer depends on the code that is calling the method. There are two cases:

我相信正确的答案取决于调用该方法的代码。有两种情况:

  1. The calling code is unsure whether the object exists, and is going to have code that will treat the case where it does not exist specially.

  2. The calling code is confident that the object exists, and indeed if it did not exists there would be some other deep problem with the logic and all you can do in this situation is give up and report an error.

  1. 调用代码不确定对象是否存在,并且将有代码专门处理它不存在的情况。

  2. 调用代码确信该对象存在,事实上,如果它不存在,那么逻辑就会存在其他一些深层问题,在这种情况下你所能做的就是放弃并报告错误。

In practice, I often implement both with a naming convention to tell them apart:

在实践中,我经常使用命名约定来实现它们以区分它们:

private MyObject findBlankOrNull() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    return null;
}

private MyObject findBlankOrFail() throws Exception {
    MyObject obj = findBlankOrNull();
    if (obj != null) {
        return obj;
    }
    throw new NoSuchFieldError("No blank piece found!");
}

Notice the OnFailversion can alway be constructed calling the other, and then throwing an exception instead of returning the null. Essentially what you are doing is inserting the Exception throw in place of the return null in order to guarantee that no null is returned, and so that you don't need to have any code to test for null at the calling site.

请注意,OnFail始终可以通过调用另一个来构造版本,然后抛出异常而不是返回 null。本质上,您正在做的是插入 Exception throw 代替 return null,以保证没有返回 null,这样您就不需要在调用站点上使用任何代码来测试 null。

I did a blog post on this topic: Return Null or Exception?that covers it in a little more detail.

我写了一篇关于这个主题的博文: Return Null or Exception? 更详细地介绍了它。

回答by Op De Cirkel

should always return an objector return null
and
the app will get a NullPointerExceptionin some edge case
those two are contradictory.

应该总是返回一个对象返回 null
并且
应用程序将NullPointerException在某些极端情况下得到一个
这两者是矛盾的。

If you are really sure that you alwasy have pieces[i].isBlank()then throw IllegalStateException

如果你真的确定你一直都有,pieces[i].isBlank()那么抛出IllegalStateException

Otherwise handle the case according your requirements.

否则按您的要求处理。

回答by Loda

if you array should always have a valid value to return, you should raise an exception as a fallback. (2sd case in your example)

如果你的数组应该总是有一个有效的值要返回,你应该抛出一个异常作为后备。(在您的示例中为 2sd 案例)

Eventually, you can declare your own kind (Class) of exception.

最终,您可以声明您自己的异常类型(类)。

回答by missingfaktor

I would suggest using Maybe(also known as Option) data type that I just talked about in another answera while ago.

我建议使用Maybe(也称为Option)数据类型,我刚才在另一个答案中谈到过。

This data type is availablein Functional Java.

这种数据类型在Functional Java 中可用

Usage:

用法:

private Option<MyObject> findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return Option.some(pieces[i]);
        }
    }
    return Option.none();
}


Sidenote:

边注:

Your findBackmethod can be generalized to a method that takes a predicate as an argument, and finds and returns the first element that satisfies it.

您的findBack方法可以泛化为一个方法,该方法将谓词作为参数,并查找并返回满足它的第一个元素。

Unsurprisingly, Functional Java already has that as well.

不出所料,Functional Java 也已经有了

Let's assume for a moment that piecesis a fj.data.List. Then your method can be rewritten as:

让我们暂时假设它pieces是一个fj.data.List. 那么你的方法可以改写为:

private Option<MyObject> findBlank() {
  return pieces.find(new F1<MyObject, Boolean>() {
    public Boolean f(MyObject p) {
      return p.isBlank();
    }
  });
}


Another sidenote:

另一个旁注:

Perhaps the above code looks pretty gnarly. IntelliJ IDEA's "closure folding" can be of some help here.

也许上面的代码看起来很粗糙。IntelliJ IDEA 的“闭包折叠”在这里可能会有所帮助