35

I'm new to android/java programming and am confused how to properly deal with this warning.

Method invocation '' may produce 'Java.lang.NullPointerException'

enter image description here

Should I be ussing assert to remove the warning? enter image description here

Or rather a runtime exception? enter image description here

Any help would be appreciated.

Hackmodford
  • 3,901
  • 4
  • 35
  • 78
  • if you check for null on the object first, the warning goes away. though you end up with a lot of unnecessary null checking if you are sure something will never be null – tyczj Apr 29 '14 at 18:06
  • Should I just disable this lint warning? – Hackmodford Apr 29 '14 at 18:09
  • I wouldn't as it can maybe bring light to something you might have overlooked but I personally just ignore it when I know something will not really be null – tyczj Apr 29 '14 at 18:10
  • 4
    I have an ocd problem when it comes to warnings :P – Hackmodford Apr 29 '14 at 18:16

8 Answers8

30

I doubt this question can be answered conclusively, as it's a matter of opinion. Or at least I believe so -- an opinion too. :)

I understand you want "0 warnings" (a very laudable goal) but there's probably not a "one size fits all" issue. That said...

Things I believe you should not do:

  • Use assert. While you can add an assert statement, Dalvik ignores them. You can configure an emulator to use them if you want, but not a real device (see Can I use assert on Android devices?). So while it would possibly remove the warning, it's useless in practice.
  • Have the method throw NullPointerException. This would be a bad idea, generally. In this case, since you're probably overriding onOptionsItemSelected(), it's not even possible.

Checking for (variable != null) is generally the best approach. What to do if it is, though, presents some other options.

  • If it's a problem you can recover from, i.e. you can continue the application even though the searchView isn't there, just do so. For example, just return from the method. It's a good idea to log this situation though, so you can spot it while testing.
  • Otherwise, if continuing isn't possible, throw an exception. You want to fail early, so that the problem can be easily detected. A reasonable exception for this case would be IllegalStateException (see Java equivalent to .NET System.InvalidOperationException). It basically indicates that this method was executed at an inappropriate time. Be careful though, that as a RuntimeException, these exceptions are unchecked, and hence will probably cause the app to crash.
Rohit
  • 13
  • 1
  • 3
matiash
  • 54,791
  • 16
  • 125
  • 154
  • Your own linked answer states it *is* possible to enable assert keyword on a real device (though obviously only via ADB). – Thorn G Jun 19 '14 at 00:11
  • @TomG AFAIK setprop can only be used on rooted devices. But maybe I'm wrong? – matiash Jun 19 '14 at 02:03
  • Ooh, you may be right -- I've only used it on rooted kiosk style devices myself. Nevermind! – Thorn G Jun 19 '14 at 02:31
  • 1
    The vast majority of these warnings come just after findViewById() calls, which can happen a LOT! As android programmers we are used to the null-pointer errors that come from these and use them to debug when making changes to layout files. Having to test Every Single One of these calls is a super pain-in-the-ass. This new "feature" (old versions of Android Studio don't have this warning) greatly increases code bloat. – SMBiggs Apr 29 '16 at 03:49
  • @ScottBiggs luckily you can now disable the warning for certain methods. See my answer below. – Iwo Banas Jul 08 '16 at 09:25
28

I started to use

@SuppressWarnings("ConstantConditions")

on simple methods where I'm sure that the id is not null.

Herrbert74
  • 2,578
  • 31
  • 51
8

What @Herrbert74 suggested it surely working fine, but sometimes it's better to not add a @SuppressWarnings("ConstantConditions") to an entire method (if it's not trivial), a better approach could be to use //noinspection ConstantConditions on the warned line.

Those are my rules of thumb:

  • Use @SuppressWarnings("ConstantConditions") when the method is simple

  • Use //noinspection ConstantConditions when the method is complex and you need to remove the warning only on a specific line

Community
  • 1
  • 1
MatPag
  • 41,742
  • 14
  • 105
  • 114
1

Yes. Using if (Object != null){} for validating is the proper way. try {} catch (NullPointerException) {} is the next solution which is preferred in this case.

If you want to get ride of it, throw an NullPointerException. Lint will ignore it in this case. public void myFunc() throws NullPointerException{}.

Anyway, good Coding always means validating everything for a possible problem while runtime. Validating != null is just fine and should always be used whenever it's possible null.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Emanuel
  • 8,027
  • 2
  • 37
  • 56
1

I like the answer to this link.

Warning is not an Error. And the warning which you are talking about says "it may produce", don't say 'it must produce'. So choice is yours. Either add null check or not

So, If you are sure that findViewById in your code will never be cause of NPE, then don't add the null check.

Community
  • 1
  • 1
Ryhan
  • 1,815
  • 1
  • 18
  • 22
1

I personally prefer using try{ }catch{ } simply because it is more elegant. However, it does add a lot of bulk to your code, if you imagine putting every, possible, NULL value into a try catch (if they are not next to each other)

Georgi Angelov
  • 4,338
  • 12
  • 67
  • 96
1

As @matiash pointed out there is no one-size-fits-all solution.

For me a good compromise was to disable NullPointerException warning for all calls to findViewById() and keep it for other method calls. That way I take responsibility for checking the resource ids but still get a benefit of getting warnings if I make other mistakes.

To achieve this I added _ -> !null method contract with Android Studio quick fix menu.

The action generated a following file file at android/support/v7/app/annotations.xml in my project root.

<root>
  <item name='android.support.v7.app.AppCompatActivity android.view.View findViewById(int)'>
    <annotation name='org.jetbrains.annotations.Contract'>
      <val val="&quot;_ -&gt; !null&quot;" />
    </annotation>
  </item>
</root>

Update: Unfortunately it doesn't survive Android Studio restarts :-( External annotations are really useful so I hope I'll figure out a way to make Android Studio load them after restart.

Iwo Banas
  • 892
  • 8
  • 12
0

I've used Objects.requireNonNull() which is a good way IMO. As @matiash mentioned, this is not a fool-proof way for every use case, but where you are sure that data won't be null, you can use this approach to get rid of the warning. And if it does fail for some unknown reason, you will get NullPointerException which you will get anyway without using this.

// before
cal.setTime(date);

// after
cal.setTime(Objects.requireNonNull(date));
Mangesh
  • 5,491
  • 5
  • 48
  • 71