I've got a MVC based Java application with three models: Room, Student and StudentRoom.
StudentRoom contains an object of Room and Student.
Now I've got the problem that if my SQL query returns no result and I check the value of student's name like this
if(studentRoom.student.name != null) {
}
I'll get a NullPointerException and I don't know how to handle it.
Should I set Student.name = ""; since my query has no result?
if(studentRoom != null && studentRoom.student != null && studentRoom.student.name != null){
//.. Access student
}
Above solution looks a bit weird. you should better use getter/setter methods instead of directly accessing the objects.
Apart from that you can define methods like isStudentAvailable() in studentRoom to check whether it has Student in it or not.
Should I set Student.name = ""; since my query has no result ?
It completely depends on your use case. But I must say better to keep it null as it will raise the exception instead of passing the null check validations.
You might need a try/catch statement for that. Something like this :
try {
// do process here
} catch (NullPointerException npe) {
//to do if student is null
}
But take note, if there are any object that is inside the try statement, a NullPointerException would still be thrown. Hope this helps.
Related
This question already has answers here:
Check chains of "get" calls for null
(11 answers)
Closed 3 years ago.
Handle Chained Method Calls avoiding NullPointerException - Which is the best way?
Let's imagine this kind of scenario:
3 class Meeting, Room, Projector
A Meeting might have set a Room and it might have a Projector inside them.
Now suppose that I want to know what is the model of the Projector.
The most natural thing is to do something like
Meeting meeting = someMethod();
return meeting.getRoom().getProjector().getModelName();
This code could return the model name of the Projector correctly,
unfortunately this code could also cause an Exeption: an java.lang.NullPointerException in case that one of the class contained into the root class Meeting (or even the Meeting class) is null.
In order to prevent this problem, and get a default value in the worst case we should check the returned value of each call.
Meeting meeting = someMethod();
if (meeting != null) {
Room room = meeting.getRoom();
if (room != null) {
Projector projector = room.getProjector();
if (projector != null) {
return projector.getModelName;
}
}
}
return "No Projector Exist";
The code now is pretty nasty.
What is the best way to deal with this kind of chained method calls avoiding the NullPointerException?
Use Optional:
return Optional.ofNullable(someMethod())
.map(Meeting::getRoom)
.map(Room::getProjector)
.map(Projector::getModelName)
.orElse("No Projector Exist");
As an aside, consider returning Optional or null from your method - having to compare your String to the special hardcoded value to detect the null case is going to get tiresome...
Checking all the null conditions in one if statement also can be done as follows.
So that the code will be much easier to read.
if (meeting != null && meeting.getRoom() != null && meeting.getRoom().getProjector() != null) {
return meeting.getRoom().getProjector().getModelName();
} else {
return "No Projector Exist";
}
The best way is to move the null checks to a private method. So when you give a meeting object, it do the required checks and return the model of the project as a string. So your code will be much simpler and with less complex.
You can catch() the NullPointerException or throw a NoRoomException and a NoProjectorException from your getRoom() and getProjector() methods and catch those.
I have code that is throwing a null pointer exception.
Here is my code:
StringBuilder strName = new StringBuilder(100);
strName.append(someClassObject.getFirstName().getContent().get(0));
strName.append(" ");
strName.append(someClassObject.getLastName().getContent().get(0));
name = strName.toString();
It is throwing a null pointer exception when trying to retrieve the last name at someClassObject.getLastName().getContent().get(0).
My question is, how to proceed with best practice in catching the null pointer.
What I was thinking something similar to this:
String lastName = (String) someClassObject.getLastName().getContent().get(0);
if(lastName == null) {
lastName = "";
LOGGER.warn("Last name is null");
}
strName.append(lastName);
Which I am hesitant since I have to convert the lastName object to a String and then create logic to check if it is null or not.
Or
try {
strName.append(someClassObject.getLastName().getContent().get(0));
} catch(NullPointerException e) {
LOGGER.warn("Last name of the conusmer is null");
}
The exception only occurs when you call a method withing an already null object (you can debug to see which object is the root null).
In case your null is the someClassObject.getLastName()
You could check nullity in java with this oneliner:
String lastName = (someClassObject.getLastName() == null) ? "" : someClassObject.getLastName().getContent().get(0);
All the overloads of StringBuilder.append() are null safe. They append the text null if the input is null. Hence, you must be getting the NPE from any one of the methods in the expression someClassObject.getLastName().getContent().get(0).
If these methods are not null safe, then it is better to check for null before chaining the next method than catching NPE. This way you might have to write some boilerplate code, but execution time will be cheaper. Exceptions are costly, even if they are handled.
The other option is, if possible change the methods getLastName(), getContent(), and get(), to make them null safe - return empty value instead of throwing NPE. In this case you have to think how the other users of these methods will react if you make this change.
You can use Java 8 Optional to check if object is not null at each level of someClassObject
, as follows:
StringBuilder strName = new StringBuilder(100);
Optional<List<String>> option = Optional.of(someClassObject)
.map(SomeClassObject::getLastName).map(LastName::getContent);
if (option.isPresent()) {
strName.append(option.get().get(0));
}
I would recommend to use the ifPresent option instead, removing the need for your if statement.
Something like:
option.ifPresent(e -> strName.append(option.get().get(0)))
I've been struggling to find why my if statement didnt work properly so I used a try catch block instead. This is the if statement as I had it:
//selectArtistByName returns an Artist object
if (!selectArtistByName(artist.getName()).equals(artist.getName()) ||
selectArtistByName(artist.getName())==null) {
//save data to database
}
When I ran the above, I got a NullPointerException because the method selectArtistByName was returning null as the database was empty. What I don't understand is why it didn't go in the if statement when I was getting null. So I did this and it worked:
try {
if (!selectArtistByName(artist.getName()).equals(artist.getName())) {
}
} catch (NullPointerException e) {
m_db.insert(TABLE_ARTIST, null, artistContents);
}
I'm not a Java guru but it looks like a horrible fix to me. How could I fix this.
You just need to change the order of condition in if block:
if (selectArtistByName(artist.getName()) == null ||
!selectArtistByName(artist.getName()).equals(artist.getName())) {
//save data to database
}
Do the null check first.
If that succeeds, then 2nd condition is not evaluated, and hence no NullPointerException. This is how short-circuit OR operator works. It only evaluates the 2nd expression, if 1st one evaluates to false.
If null check fails, then 2nd condition is evaluated, which wouldn't throw NPE, as it has already been confirmed by first condition.
Also, as rightly pointed out by #ruakh in comment, your condition seems to be broken. selectArtistByName sounds to be returning an Artist, which you can't compare with String.
I guess, you don't even need the 2nd condition. I would assume, selectArtistByName() method has already done the equality check for name, based on which it will return Artist. Just check that selectArtistByName method return null, that would be enough. So, you should change the if block to:
if (selectArtistByName(artist.getName()) == null) {
//save data to database
}
Just put the null condition check at the beginning to shortcut when artist is unknown:
if (selectArtistByName(artist.getName())==null || !selectArtistByName(artist.getName()).equals(artist.getName())) {
//save data to database
}
You can find more info about lazy evaluation in this other question: Does Java have lazy evaluation?
Product p = dao.checkProduct(pnumber);
ExpensiveProduct ep = dao.checkexpensiveProduct(pnumber);
if ((p.getNumber() == null)&&(ep.getNumber()==null) ){ // java.lang.NullPointerException
//do something
}else{
//do something
}
Why this statement giving java.lang.NullPointerException
Do I have any other way to check this?
The only non-trivial possibility where this code can throw NPE is pnumber being Integer where checkProduct() or checkexpensiveProduct() expects int (or similar).
Other trivial reasons are dao or p being null (easy to check).
Try it like this:
if ((p != null) && (p.getNumber() == null) && (ep != null) && (ep.getNumber()==null) ){
NullPointerExceptions (NPEs) occur when you call a method or access a property of a null object.
To check for nulls, you could print the values of your variables before you try to use them, or step through your program with a debugger and check what the variables' values are when you reach the line where the exception happens.
EDIT:
Regarding your comment
i need to check p.getNumber() and ep.getNumber() both returning null and get ture on that statement
your existing code
if ((p.getNumber() == null)&&(ep.getNumber()==null) )
is already doing that. Since you're getting an NPE on that line, p itself is null, or ep is null, or both. You should examine your checkProduct() and checkexpensiveProduct() methods, where p and ep are set, to see if they're working correctly.
check your p variable and ep variable .One of them is null.check
why
dao.checkProduct(pnumber)
or
dao.checkexpensiveProduct(pnumber); is returning null
What line is giving the NullPointerException? Be sure that p or ep are not null.
Before I posted this question, I already looked this, but I couldn't get what I was looking for.
I know that for the query I wrote there may exist only one row or none at all. So, there is not reason for me to use getResultList().
Here is my code:
String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
Query query=em.createQuery(hql);
query.setParameter("today",new LocalDate());
DrawUnusedBalance drawUnusedBalance=
(DrawUnusedBalance)query.getSingleResult();// we can have only a
// single datum per day
//`System.out.println(drawUnusedBalance.toString());`
The problem is, if there is no row, it throws an exception, and if not it works fine. I know the problem but I am also looking for the best solution.
What I wanted is, if there is no row in the DB I wanted to get a null object (instead of getting an exception) so I will insert a new data, if it is not null, I just want to update it.
There is one way to handle this, which I believe is not the right way to do it. It is: I will have a try-catch block and if it throws an exception I can write to insert new data in to the DB on the catch block. But I believe there will be a better way.
Yes. You need to use the try/catch block, but no need to catch the Exception. As per the API it will throw NoResultException if there is no result, and its up to you how you want to handle it.
DrawUnusedBalance drawUnusedBalance = null;
try{
drawUnusedBalance = (DrawUnusedBalance)query.getSingleResult()
catch (NoResultException nre){
//Ignore this because as per your logic this is ok!
}
if(drawUnusedBalance == null){
//Do your logic..
}
When using java 8, you may take advantage of stream API and simplify code to
return (YourEntityClass) entityManager.createQuery()
....
.getResultList()
.stream().findFirst();
That will give you java.util.Optional
If you prefer null instead, all you need is
...
.getResultList()
.stream().findFirst().orElse(null);
You mentioned getting the result list from the Query, since you don't know that there is a UniqueResult (hence the exception) you could use list and check the size?
if (query.list().size() == 1)
Since you're not doing a get() to get your unique object a query will be executed whether you call uniqueResult or list.
Another option is to use uniqueResultOptional() method, which gives you Optional in result:
String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
Query query=em.createQuery(hql);
query.setParameter("today",new LocalDate());
Optional<DrawUnusedBalance> drawUnusedBalance=query.uniqueResultOptional();
When you don't know whether there are any results, use getResultList().
List<User> foundUsers = (List<User>) query.getResultList();
if (foundUsers == null || foundUsers.isEmpty()) {
return false;
}
User foundUser = foundUsers.get(0);
String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
DrawUnusedBalance drawUnusedBalance = em.unwrap(Session.class)
.createQuery(hql, DrawUnusedBalance.class)
.setParameter("today",new LocalDate())
.uniqueResultOptional()
.orElseThrow(NotFoundException::new);