The situation is as follwing
student.studentsPhone.studentsAccount.topUp(xxx)
student is an object that has the method studentsPhone which returns the a variable of type Phone and the phone object has a method studentsAccount which returns the a variable of type Account that finally has the required method.
So my question is if I have a student object and no phone, I will get a null pointer exception. Is there a way to cut the line where we wanted?
bare in mind that I don't want to instantiate everything in the main class. I will just instantiate the Student class.
I though of several approaches
Move the method up the heirarchy, but the other objects won't be of any use really
in the studentsPhone method I say if (Phone == null) return; but its not void and there are other methods after studentPhone
You can use ternary operator for this, something like:
String result = student != null ? (student.studentPhone != null ? (student.studentPhone.studentsAccount != null ? student.studentPhone.studentsAccount.topUp(xxx) :"return"): "return") : "return"
or like:
boolean isNotNull = student != null ? (student.studentPhone != null ? (student.studentPhone.studentsAccount != null ? true : false): false) : false;
if(isNotNull){
student.studentPhone.studentsAccount.topUp(xxx);
}
You could throw your own type of runtime exception if there is no phone. Wrap your code in a try/catch block, catching your own exception and then carry on with the rest of your function
void doSomeThing() {
Phone getStudentPhone() {
if(phone == null) {
throw new noPhoneException();
}
return phone;
}
}
try {
student.getStudentPhone().studentsAccount.topUp(xxx);
} catch(noPhoneException e) {
// say something about no phone existing
}
Related
This question already has answers here:
Null check chain vs catching NullPointerException
(19 answers)
Check chains of "get" calls for null
(11 answers)
Closed 3 years ago.
I'm working with a legacy application where I often have to access properties deeply nested like that:
a.getB().getC().getD().getE().getF()
The problem is that it's possible that in any depth, the value could be null. Of course I could check each depth like that:
public Optional<F> retrieveValue(A a) {
if(a != null && a.getB() != null && a.getB().getC() != null &&
a.getB().getC().getD() != null &&
a.getB().getC().getD().getE() != null &&
a.getB().getC().getD().getE().getF() != null) {
return Optional.of(a.getB().getC().getD().getE().getF());
} else {
return Optional.empty();
}
}
F existingOrCreated = retrieveValue(a).orElse(new F());
But I have to do this in many places for many different objects so the code gets bloated with these checks. Mostly the objects are non null but there are some rare cases where objects are null. Is there a way to do it in a more concise way? I'm using Java 8 but I can't update the legacy code provided.
Before going into my answer I'd like to point out that these chains should be avoided in the first place. (Check the Law of Demeter).
Now to the problem. Because Java, unlike other languages like Kotlin does not provide simpler checking for nulls, until Java 8 you had only the choice to check each level of your object.
But since Java 8 offers function passing as parameters, I started using this feature to build my own "Safe Calls" in Java:
public static <T> Optional<T> retrieveValue(Supplier<T> getter) {
try {
return Optional.ofNullable(getter.get());
} catch (NullPointerException e) {
return Optional.empty();
}
}
Let's first see how this method is called in your given case:
F f = retrieveValue(() -> a.getB().getC().getD().getE().getF()).orElse(new F());
As you can see, we just pass a Supplier to retrieveValue and call it in a try-catch block where we catch the possible NullPointerException and return an Optional.empty() in that case.
A small disadvantage of this try-catch approach is, that it's slower than simple null check in the code if a NullPointerException occurs during checking.
Another advantage of this approach is, that this method is reusable for any other null checking in any depth and does not depend on a specific object structure.
Node node = retrieveValue(() -> root.getNode().getNode()).orElse(new Node());
Is there any chance that you could change the design such that A could simply have a getF method and the chaining is hidden in the other classes?
Something like:
public class E {
...
public F getF() {
return f; // F can be null
}
...
}
public class D {
...
public F getF() {
e == null ? null : e.getF();
}
...
}
public class C {
...
public F getF() {
d == null ? null : e.getF();
}
...
}
public class B {
...
public F getF() {
c == null ? null : e.getF();
}
...
}
public class A {
...
public F getF() {
b == null ? null : e.getF();
}
...
}
This way the null just gets propagated through the classes. You only need to check if a is null, or if a.getF() is null at the end, which will look way cleaner.
I am facing an exception while writing to the file. i am giving the code below.
private static void readCsvFromFileAmazon(List<String> filelist)
throws BiffException, IOException,NullPointerException {
FileWriter fw = new FileWriter("total_number_of_products_amazon.txt", true);
String numberOfProducts = getProductNumber(url);
System.out.println(category);
System.out.println("##############" + numberOfProducts);
// call function to get the number of products. \
if (!numberOfProducts.equals(null) || !numberOfProducts.equals(" "))
{
fw.write(numberOfProducts);
}
else
{
System.out.println("cant write null product");
}
fw.close();
}
the value getting in number of products is null then exception happening
Exception in thread "main"
##############null
java.lang.NullPointerException
exception happening in this line
if(!numberOfProducts.equals(null)||!numberOfProducts.equals(" "))
You must check numberOfProducts content in different way:
if(null != numberOfProducts ||!"".equals(numberOfProducts))
instead of if(!numberOfProducts.equals(null)||!numberOfProducts.equals(" "))
because if numberOfProducts is null, then invoke a method equals on null object throws a nullPointerException.
Hope this helps,
in your if statement numberOfProducts.equals(null)
you are comparing a string to a null string. this doesnt have any effect since you are comparing a null object.
remember that String is an object and you need to check object if they are null in this kind of way numberOfProducts == null or numberOfProducts != null
You cannot check if null.equals(null) - it throws an exception, NullPointerException, for tying to access the equals() method of null. First, make sure numberOfProducts is not null itself, using the == operator:
if (numberOfProducts == null) {
//do something
} else {
...
}
Also note that the line
if(!numberOfProducts.equals(null)||!numberOfProducts.equals(" "))
Makes no sense logically. Assuming null.equals(null) would work (IT DOES NOT), The second (right) operand - !numberOfProducts.equals(" "), will be evaluated only if numberOfProducts == null, so whenever the right operand is evaluated - it will always yield false.
This means your condition could be shortened to simply:
if (numberOfProducts != null)
As you posted for:
System.out.println("##############"+numberOfProducts);
Output is:
##############null
This means numberOfProducts is null hence if you attempt to call any non-static method on it like this:
numberOfProducts.equals(null)
will throw a NullPointerException. If you want to check if it's null, do it like this
if (numberOfProducts != null && !numberOfProducts.equals(" ")) {
fw.write(numberOfProducts);
}
I think this will work
if(numberOfProducts!=null && !numberOfProducts.rquals(" ")){
//doSomething
}else{
//doSomethingElse
}
I encounter a strange situation that is currently not that clear to me:
When having the potential null pointer access warning enabled in Eclipse, I get warnings like in the following (the warnings are stick to the line preceding the corresponding comment):
protected Item findItemByName(String itemName, Items items) {
boolean isItemNameMissing = null == itemName || itemName.isEmpty();
boolean isItemsMissing = null == items || null == items.getItems() || items.getItems().isEmpty();
if (isItemNameMissing || isItemsMissing) {
return null;
}
// potential null pointer access: the variable items might be null at this location
for (Item item : items.getItems()) {
// potential null pointer access: the variable itemName might be null at this location
if (itemName.equals(item.getName())) {
return item;
}
}
return null;
}
The same happens to me if I check for null using Guava's Preconditions like
Preconditions.checkArgument(argument != null, "argument must not be null");
Where I can understand that in the latter case a flow analysis for checking when the IllegalArgumentException will happen might be too difficult/expensive or even impossible I in turn do not understand why the compiler raises the warning at all (if I remove the checks they disappear).
Can one maybe explain how the potential null pointer access is accomplished and why it is raised in both of the cases? Or at least point me to the direction.
In the meanwhile I have a look and see whether I find it out myself...
Addendum
I've kind of broken it down to the bare core of the case. Given the following class, the warning only shows up in the method sample2 (as pointed out by the comment again). Please note that the method sample3 does not trigger the warning either.
public class PotentialNullPointerAccess {
public void sample1(final String aString) {
if (aString == null) {
return;
}
System.out.println(aString.length());
}
public void sample2(final String aString) {
boolean stringIsNull = null == aString;
if (stringIsNull) {
return;
}
// Potential null pointer access: The variable aString might be null at this location
System.out.println(aString.length());
}
public void sample3(final String aString) {
System.out.println(aString.length());
}
}
I think it is somehow answered by Ed Merks within this forum post:
http://www.eclipse.org/forums/index.php/t/278687/
From what I understand, Eclipse raises the warning once you assume a variable to potentially be null in the preceding code. You can do so by just check against null (either equal or not equal) - but you do have to have it separated somewhere as a variable, not simply as an if's solely expression.
This is probably not the cause of the warning but here you can have a null pointer.
for (Item item : items.getItems())
{
// potential null pointer access: the variable itemName might be null at this location
if (itemName.equals(item.getName()))
{
return item;
}
}
You iterate over objects, but the object returned can be null. So item.getName() can cause a null pointer exception.
Exmaple
List<String> l = new ArrayList<String>();
l.add("test");
l.add(null);
l.add("another string");
if(l == null) // <-- this is similar to the above check
return;
for(String s : l)
{
s.charAt(0); // <-- null pointer access on second item.
}
I have this method in my superclass, which extends activity:
protected boolean isStopAvailable(BusStop stop) {
if (stop == null) {
stop = new BusStop();
} else if (stop.getName().length() > 0) {
return true;
} else {
return false;
}
return false;
}
I call it in my subclass isStopAvailable(object); How is it even possible to get a null pointer exception while using a method from the object after I've initiated the object?
stop.getName() returns null
else if (stop.getName() != null && stop.getName().length() > 0)
should solve it
If getName() returns null, you will get a NPE. You are trying to do a length function on a null object, hence this exception. You should add another else if check:
...
else if (stop.getName() == null) {
// do something
}
Hope this helps.
I would bet that the name field in stop is null. Your first check is to see if the object is null, not the fields inside of it. Thus, if stop.getName() returns null, you get an NPE when attempting to invoke the length
I suggest that the NPE is thrown in this line: else if (stop.getName().length() > 0)
Thats possible because you've checked if the object BusStop is null but you didn't checked if stop.getName() could be null.
Do something like that:
else if (stop.getName() == null) {
// set stop.setName()
}
Hope this helped, Have Fun!
stop.getName() is returning null ,that is why you are getting NPE.
I have a very simple method:
public int getScore() {
return game.gameWindow.userBestScore;
}
The problem is that it can happens that game object or gameWindow do not exist. I do not want to get the Null Pointer Exception. How can catch it in a correct way? Can I do it in this way:
public int getScore() {
try{
return game.gameWindow.userBestScore;
} catch(NullPointerException e){
return -1;
}
}
Do not catch a NullPointerException.
A NullPointerException is a sign that your code is not adhering to some contract. If it is possible that game can be null, then you need to make an explicit test:
if(game != null) {
...
}
else {
...
}
If game should not be null, then you can ensure the correctness of your code by using assert.
assert game != null;
...
What is more worrying is that game seems to be a private member of your class. In this case game should probably not be null (although there are cases where this can happen). Are you initializing it properly in your constructor? I'd say that the first thing you should is to make sure that game is being initialized properly. Otherwise your code will end up being littered with un-necessary null-checks. For example, what if gameWindow in the Game class wasn't initialized properly? You would need to have another null-check for that:
if(game !== null && game.gameWindow != null) {
...
}
else {
...
}
So you should first make sure that your object's private members are being initialized properly. If they are, and it turns out that there is a valid use-case for game being null, then you would need an explicit null-check. It's always better to test for null than catching a NullPointerException. Other than the fact that exceptions should not be used to control the flow of your business logic, what if a valid NullPointerException (due to a programming error) was generated somewhere up the chain? Now your catch will catch it and you won't know about it; this can lead to some really nasty and hard-to-find bugs.
You can do that. You can also check to see if game and gameWindow are null before trying to access userBestScore.
if(game != null && game.gameWindow != null)
return game.gameWindow.userBestScore
Check whether the variables are null as shown below:
public int getScore() {
if(game == null || game.gameWindow == null){
return -1;
}
return game.gameWindow.userBestScore;
}
public int getScore() {
return ((game == null || game.gameWindow == null) ? -1 : game.gameWindow.userBestScore);
}
You can do that. OR you can check for null before you dereference those objects and take appropriate action without throwing an exception. That'll be more efficient.
The real question you should be asking is: Why on earth would an object have null references for private data members? You aren't constructing your objects properly. An object should be properly initialized and 100% ready to go after you create it. Otherwise, you end up having to be unnecessarily defensive in your code.
Avoid exception throwing as much as possible. Handling the known issues is the better way than throwing exceptions.
In some where you have to do a null check. Probably before calling the getScore() method, because that doesn't make a sense of calling that method if the game or gameWindow is null.
if (game != null && gameWindow != null)
{
int score = getScore();
}
OR
public int getScore()
{
if (game != null && gameWindow != null)
{
return game.gameWindow.userBestScore;
}
else
{
return -1;
}
}
Don't do duplicate null checkings.