I got this piece of code from a commercial product. I believe that it will always throw the java.lang.NullPointerException exception when this.result is null. Am I right to say that?
private void closeCurrentResult() throws SQLException {
this.lastUpdateCount = -1;
if(this.result != null) {
this.result.close();
}
this.result = null;
}
if this.result is null, then
this.result = null
is equivalent to
null = null;
while causes the NPE.
After read through some of the replies, I think the thing becomes clear. I also did a test as the code shown below:
public class NullTest {
public static void main(String[] args) {
ABC a = new ABC(null);
a.test();
}
static class ABC {
Object result;
ABC(Object result) {
this.result = result;
}
void test() {
if (this.result != null) {
System.out.println("do something");
}
this.result = null;
}
}
}
And it works just fine.
Let's go through it step by step:
first this.lastUpdateCount = -1; does nothing but setting a global member variable to -1.
if(this.result != null)
This one (guard clause) tests, whether result is null if not so this.result.close(); the close() method on result is called. The guard says, it's safe to do so. After that this.result = null; sets result to null anyways.
After this codeblock, two things are assured:
1) this.result is null
2) And if this.result had something open it is now close
if this.result is null, then this.result = null is equivalent to null = null;
this.result = is an assignment statement: You are assigning something to this.result, whose value may be null. This operation is NPE-safe.
No..
this.result = null simply assigns null reference to this.result.
It will throw NPE only when this == null, which is...never.
NPE means you invoked a method or referred a property on a null reference. That is to say, when your code is like this:
obj.someProperty or obj.someMethod() when obj itself is null.
BTW, null reference is a special reference (instead of a special value or some compile-time mechanism).
All the null reference is identical (same reference).
String a = null;
Person p = null;
assert a == b;
null reference is the "default value" for reference-type variables.
class Person{
String name; // `name` is null until assigned otherwise.
}
NPE will be thrown when unboxing a null reference variable.
Integer a = null;
int b = a; // throws NPE.
Many JDK methods threat null reference specially.(Which is good and bad.)
String a = null;
System.out.println(a);
// will NOT throw NPE because:
// PrintStream.java:
public void println(String var1) {
synchronized(this) {
this.print(var1);
this.newLine();
}
}
Another example:
String b = null;
String a = String.valueOf(b);
// a is String "null" instead of null reference. Because:
// String.java:
public static String valueOf(Object var0) {
return var0 == null?"null":var0.toString();
}
No, you are not.
This:
if(this.result != null) {
this.result.close();
}
Call close() only if this.result is not null, correct.
This would have thrown a NullPointerException if the check would have been this.result != null.
The last line:
this.result = null;
Simply set this.result as null, nothing wrong here either.
The result is like a label to a memory address. When result is not null, it's pointing to some memory address where there is an object.
When you use the assignment operator =, as in result = null, you're saying, "make result point to null and I don't care what it was originally pointing at". So whatever result is currently pointing to does not matter, even if it's null, reassigning result to null will not throw a NPE.
The code you posted won't throw a null pointer exception. But after setting the result as null you try to access any method it will throw a null pointer exception.
private void closeCurrentResult() throws SQLException {
this.lastUpdateCount = -1;
if(this.result != null) {
this.result.close();
}
this.result = null;
this.result.someMethod(); //Will throw a Null Pointer Exception
}
Related
I have a class as below, before I set the data I need to check whether getValue() is present and it's value is empty.
public class Money {
{
private String value;
private String currency;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getCurrency() {
return currency;
public void setCurrency(String currency) {
this.currency = currency;
}
}
//JSON is like this
"money": {
"currency": "USD",
"value": ""
}
I want to check whether this getValue() is present or not like obj.getMoney().getValue() != null,
and then I need to check it's value is empty... obj.getMoney().getValue().equals("") but it fails on this condition obj.getMoney().getValue() != null as null.
If the following check fails
if (obj.getMoney().getValue() != null) { ... }
then it implies that the money object itself is null. In this case, you can slightly modify your if condition to check for this:
if (obj.getMoney() != null && obj.getMoney().getValue() != null) { ... }
You said that first you need to check whether value is null or not and then also check whether the value is empty or not,
You can do the following
if (obj.getMoney() != null && obj.getMoney().getValue() != null && !obj.getMoney().getValue().isEmpty()) {
// rest of the code here
}
obj.getMoney().getValue() will give you null pointer exception. You should check for null object before using . after it. Example code:
Below code looks huge but it's actually readable and it will be optimized by compiler.
if(obj != null){
Money money = obj.getMoney();
if(money != null) {
String value = money.getValue();
//Add you logic here...
}
}
I think you are getting null point exception. You are facing this exception because obj.getMoney() is already null. Since you are trying to get a null object's value, so you are getting this exception. Correct code will be
if ((obj.getMoney() != null) && (obj.getMoney().getValue().trim().length() > 0)) {
// Execute your code here
}
When instantiating your obj, gives a new. The form of validation is correct, the problem is in the obj that was not initialized. (I believe)
This might be a very basic question, but I still don't know the answer.
String abc = null;
System.out.println(abc);
Why does System.out.println print "null" and does not throw NullPointerException?
It's behaving as it's documented to. PrintStream.println(String) is documented as:
Prints a String and then terminate the line. This method behaves as though it invokes print(String) and then println().
PrintStream.print(String) is documented as:
Prints a string. If the argument is null then the string "null" is printed. Otherwise, the string's characters are converted into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.
When in doubt, read the documentation :)
Because it eventually reaches the print method, which prints "null" for a null String :
public void println(String x) {
synchronized (lock) {
print(x);
println();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
The same behavior exists for printing of any null reference (in this case the "null" String is returned by String.valueOf(null) :
public void println(Object x) {
String s = String.valueOf(x);
synchronized (lock) {
print(s);
println();
}
}
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
You can just have a look at PrintStream source code:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
As you can see, the null case is handled by just printing "null".
Null is special cased inside the print function:
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
According to PrintStream#println()
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
According to String#valueOf
Returns the string representation of the Object argument.
If the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
System.out.print function source code. If print string is null ,it sets to "null"
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
Well in some circumstances, System.out.println could throw a NullPointerException making you think that is how it works.
If you have a complex object where you have created your own toString() method, there is a potential for the error to occur within that method. You could either accidentally or purposely code that such that the NPE does occur. The object itself is not null, however some of the attributes inside might be null.
Such coding should most likely be discouraged though because it does break the contract as others have pointed out. The desired behavior is to represent a null object as null and not NPE being thrown.
Here below is a code snippet in java.
Collection contextPages = (Collection) getContextPages();
Iterator contextPageIter = contextPages.iterator();
while (contextPageIter.hasNext()) {
Page contextPage = (Page) contextPageIter.next();
String result = contextPage.getResult(); // <-- Null pointer exception here
// Other stuff which this API does.
}
This code has been in production for a while. But for some reason, we hit a null pointer at String result = contextPage.getResult();.
So looks like even though we did a check for hasNext(), the next() method is returning null.
One possibility is that the collection itself has a null, but is it possible that this code could yield to a null pointer in a multi-threaded environment?
Some collections allow you to add a null, so iter.next will return it and when you use it -> NPE
To demonstrate
#Test
public void testNull() {
Collection<Object> c = new ArrayList<>();
c.add(null);
Iterator<Object> iterator = c.iterator();
Assert.assertTrue(iterator.hasNext());
Object o = iterator.next();
Assert.assertNull(o);
}
So check that you don't add null references to the collection or check for null before using the result of Iterator#next()
Page contextPage = (Page) contextPageIter.next();
String result = null;
if(contextPage != null) {
result = contextPage.getResult();
}
There should be no difference between single- and multi- threaded applications, just make sure you don't add null.
Better to check for null before using the result of Iterator.next()
Try this -
Page contextPage = (Page) contextPageIter.next();
String result = null;
if(contextPage != null) {
result = contextPage.getResult();
}
Please have a look on following Class, I need to check if there is valid value in the variable. All works fine if there is a proper value in variable instead of null, When it comes null the behaviour is not what I expect (Although it might make sense if Integer a = null; when checked as a instanceof Integer,
Can some one guide me how to achieve correct result from following class?
package com.mazhar.hassan;
public class ValueChecker {
public static boolean empty(Integer value) {
System.out.println("Integer");
return (value != null && value.intValue() > 0);
}
public static boolean empty(Long value) {
System.out.println("Long");
return (value != null && value.longValue() > 0);
}
public static boolean empty(String value) {
System.out.println("String");
return (value != null && value.length() > 0);
}
public static boolean empty(Object value) {
System.out.println("Object");
return (value != null);
}
public static void checkAll(Object... args) {
for(Object o: args) {
if (o instanceof Integer) {
empty((Integer)o);
}
else if (o instanceof Long) {
empty((Long)o);
}
else if (o instanceof String) {
empty((String)o);
}
else {
empty(o);
}
}
}
public static void main (String[] args) {
Integer a = null;
Long b = null;
String x = null;
Object y = null;
if (a instanceof Integer) {
System.out.println("a is Integer");
} else {
System.out.println("a is not Integer");
}
System.out.println("/---------------------------------------------------/");
checkAll(a,b,x,y);
System.out.println("/---------------------------------------------------/");
empty(a);
empty(b);
empty(x);
empty(y);
}
}
Why I need exact type checking is, I thave to throw erros like "Not valid Integer", "No valid Long" etc.
The output of above class is as follows.
/-----------------------(Output 1)----------------------------/
a is not Integer
/-----------------------(Output 2)----------------------------/
Object
Object
Object
Object
/------------------------(Output 3)---------------------------/
Integer
Long
String
Object
Output 1: a is not integer (checked by instanceof) can not recognize it but when passed to a overloaded function goes to the right function (Output 3)
Output 2: How to achieve checkAll with multiple/dynamic param checkAll(varInt, varLong, varString, varObject)
The behaviour for Output 1 is caused by the fact that method overloads are bound at compile time. So the specific overload to pick is bound before the program even runs. instanceof, on the other hand, is a runtime check.
Thus, at runtime a instanceof Integer is effectively null instanceof Integer, which is obviously false.
But for each of those individual method calls, the proper method is called because the compiler bound the specific overload of the method at compile time, based on the reference type of the variable. Thus:
empty(a); // Compiled to a call to empty(Integer value)
empty(b); // Compiled to a call to empty(Long value)
empty(x); // Compiled to a call to empty(String value)
empty(y); // Compiled to a call to empty(Object value)
So regardless of the actual object that a, b, x, and y reference, you'll always get the right output on your console for the respective object.
Output 2: How to achieve checkAll with multiple/dynamic param checkAll(varInt, varLong, varString, varObject)
Well, if you're going to pass null, you can't really. null is null at runtime, and doesn't have any type information associated with it. The JVM can't tell that one null is a "String null" or an "Object null". It's just null. So you can't really implement the multiple check you want to for null inputs -- null instanceof ______ will always return false, so you'll always end up with your default case.
If you pass actual objects, though, that method should work properly.
problem:
Integer a = null;
Long b = null;
String x = null;
Object y = null;
You cant use instanceof on null values, it expect the objects to be instantiated thus giving you wrong result.
solution:
instantaite the object first before you check for instance.
The problem here is that when you check instanceof in your loop, you are checking null. null is not an instance of anything, it is the absence of an instance.
If you want to achieve something like this, you're going to have to change your API for checkAll(Object ...) to something that tells the function what types to expect:
public class ValueChecker {
public static boolean checkAll(Object[] args, Class<?>[] types) {
if (args == null || types == null || args.length != types.length)
throw new RuntimeException("programming error");
for (int i = 0; i < args.length; i++) {
if (types[i] == null)
throw new RuntimeException("programming error");
if (args[i] == null || !types[i].isAssignableFrom(args[i].getClass())) {
System.out.println("arg " + (i +1) + " is not " + types[i].getSimpleName());
return false;
}
}
return true;
}
public static void main(String[] args) {
Integer a = null;
Long b = null;
String x = null;
Object y = null;
checkAll(
new Object[] {a, b, x, y},
new Class<?>[] {Integer.class, Long.class, String.class, Object.class}
);
}
}
I have a simple dataset class similar to:
class DataSet {
private String value;
private String additionalValue;
public DataSet(String value, String additionalValue) {
this.value = value;
this.additionalValue = additionalValue;
}
public String getAdditionalValue() {
return this.additionalValue;
}
}
Then I have created an ArrayList<DataSet> and added a new element DataSet("Value1", null).
Now at some point I need to check if the entry with value "Value1" has additionalValue and if it does, what it is.
I do a simple loop checking if value.equals("Value1") == true, then I do:
if (element.getAdditionalValue() != null) {
return element.getAdditionalValue();
}
However, as soon as it gets to the if statement, it throws an error saying that the value is null.
How can I make it so that it doesn't throw an error and just skips the return statement if additionalValue is null?
EDIT:
But the thing is that the element cannot be null at the point where it checks additionalValue as it passed through the element.getValue.equals("Value1") condition.
for (DataSet element : dataSet) {
if (element.getValue.equals("Value1")) {
if (element.getAdditionalValue() != null) {
return element.getAdditionalValue();
}
}
}
I think the problem is that your element object is null, so you have to check it before checking additionalValue.
if (element != null && element.getAdditionalValue() != null){
return element.getAdditionalValue();
}
This will sort you out:
if (element != null && element.getAdditionalValue() != null) {
return element.getAdditionalValue();
}