Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
117 views
in Technique[技术] by (71.8m points)

java - 避免!=空语句(Avoiding != null statements)

I use object != null a lot to avoid NullPointerException .

(我经常使用object != null来避免NullPointerException 。)

Is there a good alternative to this?

(有没有好的替代方法?)

For example:

(例如:)

if (someobject != null) {
    someobject.doCalc();
}

This avoids a NullPointerException , when it is unknown if the object is null or not.

(如果不知道对象是否为null ,则可以避免NullPointerException 。)

Note that the accepted answer may be out of date, see https://stackoverflow.com/a/2386013/12943 for a more recent approach.

(请注意,接受的答案可能已过期,请参阅https://stackoverflow.com/a/2386013/12943以获取最新的方法。)

  ask by community wiki translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This to me sounds like a reasonably common problem that junior to intermediate developers tend to face at some point: they either don't know or don't trust the contracts they are participating in and defensively overcheck for nulls.

(在我看来,这似乎是一个相当普遍的问题,初级和中级开发人员往往会在某个时候遇到这些问题:他们要么不知道,要么不信任他们所参与的合同,并且防御性地检查了null。)

Additionally, when writing their own code, they tend to rely on returning nulls to indicate something thus requiring the caller to check for nulls.

(另外,在编写自己的代码时,他们倾向于依靠返回空值来表示某些内容,因此要求调用者检查空值。)

To put this another way, there are two instances where null checking comes up:

(换句话说,在两种情况下会出现空检查:)

  1. Where null is a valid response in terms of the contract;

    (如果为null,则表示合同中的有效回复;)

    and

    (和)

  2. Where it isn't a valid response.

    (无效的地方。)

(2) is easy.

((2)容易。)

Either use assert statements (assertions) or allow failure (for example, NullPointerException ).

(使用assert语句(断言)或允许失败(例如NullPointerException )。)

Assertions are a highly-underused Java feature that was added in 1.4.

(断言是1.4中新增的一个未被充分利用的Java功能。)

The syntax is:

(语法为:)

assert <condition>

or

(要么)

assert <condition> : <object>

where <condition> is a boolean expression and <object> is an object whose toString() method's output will be included in the error.

(其中, <condition>是布尔表达式, <object>是一个对象,其toString()方法的输出将包含在错误中。)

An assert statement throws an Error ( AssertionError ) if the condition is not true.

(如果条件不成立,则assert语句将引发ErrorAssertionError )。)

By default, Java ignores assertions.

(默认情况下,Java会忽略断言。)

You can enable assertions by passing the option -ea to the JVM.

(您可以通过将选项-ea传递给JVM来启用断言。)

You can enable and disable assertions for individual classes and packages.

(您可以启用和禁用单个类和程序包的断言。)

This means that you can validate code with the assertions while developing and testing, and disable them in a production environment, although my testing has shown next to no performance impact from assertions.

(这意味着尽管我的测试几乎没有显示断言对性能的影响,但是您可以在开发和测试时使用断言来验证代码,并在生产环境中禁用它们。)

Not using assertions in this case is OK because the code will just fail, which is what will happen if you use assertions.

(在这种情况下,不使用断言是可以的,因为代码只会失败,这就是使用断言时会发生的情况。)

The only difference is that with assertions it might happen sooner, in a more-meaningful way and possibly with extra information, which may help you to figure out why it happened if you weren't expecting it.

(唯一的区别是,有了断言,它可能会更早地发生,以更有意义的方式出现,并可能带有额外的信息,这可以帮助您弄清楚为什么不期望它会发生。)

(1) is a little harder.

((1)有点难。)

If you have no control over the code you're calling then you're stuck.

(如果您无法控制正在调用的代码,那么您将陷入困境。)

If null is a valid response, you have to check for it.

(如果null为有效响应,则必须检查它。)

If it's code that you do control, however (and this is often the case), then it's a different story.

(但是,如果您控制的是代码(通常是这种情况),那就是另一回事了。)

Avoid using nulls as a response.

(避免使用null作为响应。)

With methods that return collections, it's easy: return empty collections (or arrays) instead of nulls pretty much all the time.

(使用返回集合的方法很容易:几乎总是返回空集合(或数组)而不是null。)

With non-collections it might be harder.

(使用非集合,可能会更困难。)

Consider this as an example: if you have these interfaces:

(以这个为例:如果您具有以下接口:)

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

where Parser takes raw user input and finds something to do, perhaps if you're implementing a command line interface for something.

(在Parser中,原始的用户输入会找到要执行的操作,如果您正在为某些操作实现命令行界面的话。)

Now you might make the contract that it returns null if there's no appropriate action.

(现在,如果没有适当的操作,您可以使合同返回null。)

That leads the null checking you're talking about.

(这导致您正在谈论的空检查。)

An alternative solution is to never return null and instead use the Null Object pattern :

(另一种解决方案是从不返回null,而使用Null Object模式 :)

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Compare:

(比较:)

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

to

(至)

ParserFactory.getParser().findAction(someInput).doSomething();

which is a much better design because it leads to more concise code.

(这是一个更好的设计,因为它可以导致代码更简洁。)

That said, perhaps it is entirely appropriate for the findAction() method to throw an Exception with a meaningful error message -- especially in this case where you are relying on user input.

(也就是说,对于findAction()方法来说,抛出带有有意义的错误消息的Exception异常是完全适当的-特别是在这种情况下,您依赖于用户输入。)

It would be much better for the findAction method to throw an Exception than for the calling method to blow up with a simple NullPointerException with no explanation.

(对于findAction方法抛出一个异常,比对一个没有解释的简单NullPointerException进行抛出的调用方法要好得多。)

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

Or if you think the try/catch mechanism is too ugly, rather than Do Nothing your default action should provide feedback to the user.

(或者,如果您认为try / catch机制太丑陋,而不是什么都不做,则默认操作应向用户提供反馈。)

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...