How to trace a NullPointerException in a chain of

2019-01-11 16:50发布

If I get a NullPointerException in a call like this:

someObject.getSomething().getSomethingElse().
    getAnotherThing().getYetAnotherObject().getValue();

I get a rather useless exception text like:

Exception in thread "main" java.lang.NullPointerException
at package.SomeClass.someMethod(SomeClass.java:12)

I find it rather hard to find out wich call actually returend null, often finding myself refactoring the code to something like this:

Foo ret1 = someObject.getSomething();
Bar ret2 = ret1.getSomethingElse();
Baz ret3 = ret2.getAnotherThing();
Bam ret4 = ret3.getYetAnotherOject();
int ret5 = ret4.getValue();

and then waiting for a more descriptive NullPointerException that tells me which line to look for.

Some of you might argue that concatening getters is bad style and should be avoided anyway, but my Question is: Can I find the bug without changing the code?

Hint: I'm using eclipse and I know what a debugger is, but I can't figuere out how to apply it to the problem.

My conclusion on the answers:
Some answers told me that I should not chain getters one after another, some answers showed my how to debug my code if I disobayed that advice.

I've accepted an answer that taught me excactly when to chain getters:

  • If they cannot return null, chain them as long as you like. No need for checking != null, no need to worry about NullPointerExceptions (be warned that chaining still vialotes the law of demeter, but I can live with that)
  • If they may return null, don't ever, never ever chain them, and perform a check for null values on each one that may return null

This makes any good advice on actual debugging useless.

11条回答
家丑人穷心不美
2楼-- · 2019-01-11 17:12

Early failure is also an option.

Anywhere in your code that a null value can be returned, consider introducing a check for a null return value.

public Foo getSomething()
{
  Foo result;
  ...
  if (result == null) {
    throw new IllegalStateException("Something is missing");
  }
  return result;
}
查看更多
我想做一个坏孩纸
3楼-- · 2019-01-11 17:21

Chained expressions like that are a pain to debug for NullPointerExceptions (and most other problems that can occur) so I would advise you to try and avoid it. You have probably heard that enough though and like a previous poster mentioned you can add break points on the actual NullPointerException to see where it occurred.

In eclipse (and most IDEs) you can also use watch expressions to evaluate code running in the debugger. You do this bu selecting the code and use the contet menu to add a new watch.

If you are in control of the method that returns null you could also consider the Null Object pattern if null is a valid value to return.

查看更多
你好瞎i
4楼-- · 2019-01-11 17:22

If you're having to get to the point where you're splitting up the line or doing elaborate debugging to spot the problem, then that's generally God's way of telling you that your code isn't checking for the null early enough.

If you have a method or constructor that takes an object parameter and the object/method in question cannot sensibly deal with that parameter being null, then just check and throw a NullPointerException there and then.

I've seen people invent "coding style" rules to try and get round this problem such as "you're not allowed more than one dot on a line". But this just encourages programming that spots the bug in the wrong place.

查看更多
不美不萌又怎样
5楼-- · 2019-01-11 17:27

NPE is the most useless Exception in Java, period. It seems to be always lazily implemented and never tells exactly what caused it, even as simple as "class x.y.Z is null" would help a lot in debugging such cases.

Anyway, the only good way I've found to find the NPE thrower in these cases is the following kind of refactoring:

someObject.getSomething()
          .getSomethingElse()
          .getAnotherThing()
          .getYetAnotherObject()
          .getValue();

There you have it, now NPE points to correct line and thus correct method which threw the actual NPE. Not as elegant solution as I'd want it to be, but it works.

查看更多
贪生不怕死
6楼-- · 2019-01-11 17:27

In IntelliJ IDEA you can set exceptionbreakpoints. Those breakpoints fire whenever a specified exception is thrown (you can scope this to a package or a class).

That way it should be easy to find the source of your NPE.

I would assume, that you can do something similar in netbeans or eclipse.

EDIT: Here is an explanation on how to add an exceptionbreakpoint in eclipse

查看更多
萌系小妹纸
7楼-- · 2019-01-11 17:28

Here's how to find the bug, using Eclipse.

First, set a breakpoint on the line:

someObject.getSomething().getSomethingElse().
getAnotherThing().getYetAnotherObject().getValue();

Run the program in debug mode, allow the debugger to switch over to its perspective when the line is hit.

Now, highlight "someObject" and press CTRL+SHIFT+I (or right click and say "inspect").

Is it null? You've found your NPE. Is it non-null? Then highlight someObject.getSomething() (including the parenthesis) and inspect it. Is it null? Etc. Continue down the chain to figure out where your NPE is occurring, without having to change your code.

查看更多
登录 后发表回答