Java HashMap get method null pointer exception
I typed out the code manually into SO — apologies for both the errors. Thanks very much for the answers, everyone. I’ll make the edits.
9 Answers 9
If c is not contained in myMap , it will return null , which can’t be unboxed as a boolean .
Boolean b = myMap.get(c); if(b != null && b)< .
This is the correct answer. Also, HashMap myMap
If myMap doesn't contain a key that matches c , then myMap.get(c) will return null. In that case, when the JVM unboxes what it expects to be a java.lang.Boolean object into a boolean primitive to execute the condition, it founds a null object and therefore throws a java.lang.NullPointerException .
The following block is equivalent to what you have in your example and should make it easier to understand why you would have a NullPointerException :
if (((Boolean) myMap.get(c)).booleanValue())
I would re-write your original condition as:
if ( myMap.containsKey(c) && myMap.get(c))
If there is no entity with required Character in map, then map.get(key) returns null and inside if statement it leads to NullPointerException throwing.
A stab in the dark: is there an entry in your map for the particular character assigned to c ? If there isn't, Java may be trying to unbox a null value.
for ( char c : input.toCharArray() )
for ( char c : input.toCharArray() )
Will make use of the map's defined method to check if a certain key is registered on the map. I'm leaving the for as it is, since you seem to want to check for a group of keys.
myMap.get(c) returns the value associated with that key, or null if the key is not registered.
As a side note, remember that if you use this method with custom objects you'll have to redefine the hashcode and equals methods.
Suggestion: I'm just suggesting this out of a remote idea I have, if it's not a correct interpretation of your code just ignore it. If your map only contains a boolean value to determine if certain value "is contained" or not, I strongly suggest you use a HashSet instead because a map is not doing any sense in that context.
Find out what variable is throwing a NullPointerException programmatically
I would like to know if there's a generic way to find out programatically what variable (not just the line) is throwing the NullPointerException in a certain area of code. In the example, knowing that
Hm, it would be easier to find the NullPointerException if this wasn 't a one-liner. It is really hard to follow such code.
Considering your options, I'd just point that "too much work" might actually mean a lot less work in the long run.
8 Answers 8
Since it's possible to cause a null pointer exception without even involving a variable:
throw new NullPointerException();
I would have to say that there is no generic way to pin down a null pointer exception to a specific variable.
Your best bet would be to put as few as possible statements on each line so that it becomes obvious what caused the null pointer exception. Consider refactoring your code in the question to look something like this:
List items = this.superSL.items; String name = items.get(name); String source = name.getSource(); if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0) < // . >
It's more lines of code to be sure. But it's also more readable and more maintainable.
You might consider, as announced here, the JDK 14 which should include the JEP 358:
JEP 358: Helpful NullPointerExceptions
Suppose an NPE occurs in this code:
The filename and line number do not pinpoint exactly which variable was null.
Was it a or b or c ?
A similar problem occurs with array access and assignment. Suppose an NPE occurs in this code:
The filename and line number do not pinpoint exactly which array component was null.
Was it a or a[i] or a[i][j] ?
Description:
If the more complex statement a.b.c.i = 99; throws an NPE, the message would dissect the statement and pinpoint the cause by showing the full access path which led up to the null:
Exception in thread "main" java.lang.NullPointerException: Cannot read field "c" because "a.b" is null at Prog.main(Prog.java:5)
Again: to be tested with JDK 14.
For the expression a[i][j][k] , there’s also the possibility that either, i , j , or k has type Integer and is null, so unboxing fails.
In real life scenarios, the expression to the right of the = might bear potential for NPE too.
I tried with jdk-14.0.1
it works; it produces a message like
Cannot invoke "java.lang.Integer.intValue()" because "i" is null then.
When the method has been compiled without debug information, it will use something like " " instead of " i ", but that’s unavoidable.
For the expression a[i][j][k] , there’s also the possibility that either, i , j , or k has type Integer and is null , so unboxing fails. In real life scenarios, the expression to the right of the = might bear potential for NPE too.
I didn’t try, but since this is easy to spot in the execution (the cause being an invocation of intValue() on a null reference) and determining the sub-expression is not different to identifying, e.g. a[i] being null , I’d expect this. I think, I will make a try later this day.
Just verified that it works; it produces a message like Cannot invoke "java.lang.Integer.intValue()" because "i" is null then. When the method has been compiled without debug information, it will use something like "
Sorry, no, there is not a simple programmatic way to determine which variable or method call is the source of the exception. You could use something like Aspect-Oriented Programming (AOP), e.g. AspectJ, but this is not inherent to the language and is not generally incorporated into a program simply for debugging purposes.
I know you don't want to hear this, but these are simply the cost of doing business.
if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)
It is unusual to see so many strung together method calls. I believe you best bet is to get in the habit of breaking these up more - not necessary down to 1 call per line, but fewer than this. Why?
1) Correctness - is it valid in the design for one of these calls to return null? If so, you should break it out, test it, and handle it appropriately.
2) Understandability - it would be easier for future maintainers (including future you) to understand if you intermediate, well-named variables to help clarify what is happening on this line.
3) Efficiency - usually when you go so deep into a graph (stringing together a series of method calls), its likely you will need to go back down around there later. Capturing this intermediate value in an intermediate variable means avoiding making one or more method calls again.
4) Debugging - as indicating by your question, spltiting a complex line like this up simplifies debugging. by narrowing down the possible source of the exception.
If/else statement not completing, giving me NullPointerException error
I'm using Jsoup to parse an amazon link. I'm trying to figure out a way for the code to search for a specific element; if it finds it, complete action; if it doesn't, look for a different specific element and complete action etc. Here's my code:
protected Void doInBackground(Void. params) < //String url = "http://www.amazon.com/gp/product/B00FRDUZXM/ref=s9_simh_gw_p14_d0_i2?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=desktop-4&pf_rd_r=0ZV79CBKAVKNW0RD843D&pf_rd_t=36701&pf_rd_p=1970566762&pf_rd_i=desktop"; String url = "http://www.amazon.com/VeggieTales-Very-Merry-Larry-Christmas/dp/B00H2T37SO/ref=pd_rhf_gw_p_img_3"; //String url = "http://www.amazon.com/Sony-A7-A7R-Snapshots-Great/dp/0321968603/ref=pd_rhf_gw_p_img_4"; try < // Connect to the web site Document document = Jsoup.connect(url).get(); // Get the html document title Elements trs = document.select("table.a-lineitem"); if(trs != null) < Elements tds = trs.select("span"); Element price1 = tds.first(); System.out.println(price1); String str1 = price1.text(); System.out.println(str1); String str2 = str1.replaceAll( "[$,]", "" ); double aInt = Double.parseDouble(str2); System.out.println("Price: " + aInt); >else < Elements prices = document.select("table.product b.priceLarge"); if(prices != null) < String priceWithCurrency = prices.text(); System.out.println(priceWithCurrency); System.out.println(priceWithCurrency); String priceAsText = priceWithCurrency.replaceAll( "[$,]", "" ); double priceAsNumber = Double.parseDouble(priceAsText); System.out.println("Price: " + priceAsNumber); >else < Elements prices2 = document.select("div.a-row span.a-size-medium a-color-price"); String priceWithCurrency2 = prices2.text(); System.out.println(priceWithCurrency2); String priceAsText2 = priceWithCurrency2.replaceAll( "[$,]", "" ); double priceAsNumber2 = Double.parseDouble(priceAsText2); System.out.println("Price: " + priceAsNumber2); >> > catch (IOException e) < e.printStackTrace(); >return null; >
I'm positive I'm looking for the correct element on the page (as in, table.a-lineitem and the other two selected elements aren't the problem, so I have to assume it's something to do with my if/else statement. Any ideas? Here's the error:
12-17 23:10:05.145 10907-11060/nathanieljones.amazonpricechecker E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #3 Process: nathanieljones.amazonpricechecker, PID: 10907 java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:300) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) at java.util.concurrent.FutureTask.setException(FutureTask.java:222) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.jsoup.nodes.Element.text()' on a null object reference at nathanieljones.amazonpricechecker.MainActivity$Title.doInBackground(MainActivity.java:102) at nathanieljones.amazonpricechecker.MainActivity$Title.doInBackground(MainActivity.java:73) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) 12-17 23:10:05.834 10907-10907/nathanieljones.amazonpricechecker E/WindowManager﹕ android.view.WindowLeaked: Activity nathanieljones.amazonpricechecker.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView that was originally added here at android.view.ViewRootImpl.(ViewRootImpl.java:363) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:261) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) at android.app.Dialog.show(Dialog.java:298) at nathanieljones.amazonpricechecker.MainActivity$Title.onPreExecute(MainActivity.java:83) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587) at android.os.AsyncTask.execute(AsyncTask.java:535) at nathanieljones.amazonpricechecker.MainActivity$1.onClick(MainActivity.java:57) at android.view.View.performClick(View.java:4756) at android.view.View$PerformClick.run(View.java:19749) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)