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?
Related
Here is my code
if (!multipartFile.isEmpty() && multipartFile.getOriginalFilename() != null && !multipartFile.getOriginalFilename().isBlank()) {
String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}
Here is how I see that code
As you can see, the last part of IF condition is underlined as Idea thinks that getOriginalFilename can return null, but I've checked this with that line of a code
multipartFile.getOriginalFilename() != null. What am I doing wrong?
Idea thinks that getOriginalFilename can return null
Because it can.
but I've checked this with that line of a code multipartFile.getOriginalFilename() != null
You checked that the previous invocation did not return null. The next one still can.
What am I doing wrong?
Calling a method twice in rapid succession, instead of storing its result in a variable and using that one for the check and the further processing. In fact you then call it for a 3rd time.
(this was just a copy of my comment from above)
While there may be ways to simplify the condition as the other answer shows, as you also need the result of getOriginalFilename() inside the if, I would assume the IDE will complain about that one next, and at the end you will probably have to bite the bullet and have a variable for it:
String originalFilename = multipartFile.getOriginalFilename();
if (!multipartFile.isEmpty() && originalFilename != null && !originalFilename.isBlank()) {
String fileName = StringUtils.cleanPath(originalFilename);
dishCreationDto.setImageFileName(fileName);
dishService.saveWithFile(dishCreationDto, multipartFile);
} else {
dishService.save(dishCreationDto);
}
You could simplify that expression by using the StringUtils:
!StringUtils.isNullOrEmpty(multipartFile.getOriginalFilename())
There are other functions in that utility class that might be helpful depending on what you're trying to do.
IntelliJ isn't always right but is always good to look a bit more in detail to our code to see what can be improved/simplified for better debugging/readability.
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.
I am currently facing an issue with my code and I can't figure out why this statement is evaluating as it is. This is the first time I am using a finally block, so it may be that there is some fundamental behaviour I haven't understood.
What this method does is it gets a json document from an api and stores said document as this.thisPage. Then another method sliceItem does the splitting of the results field into an array of json objects.
A MalformedJsonException is thrown whenever the API returns a json that has bad fields (ex. String fields being stored as int, or int as double etc.). This is tried 10 times (handled by failsafeget) and if it failed 10 times, MalformedJsonException (RuntimeException) is thrown. What I would like slicePage to do in that case is get the next page instead of continuing with this page. To simplify this - each page has 100 entries; if the offset 3500 is broken, we want to get offset 3600.
The issue that I am facing currently is that resp always evaluates to null in the final block. I cannot understand why this is the case, since the try block can return something other than null (JSONObject type).
Any help would be greatly appreciated and if you need more information/code, I am willing to provide it.
public synchronized void slicePage(){
JSONObject resp=null; // otherwise java complains that not initialised
ApiClient apiClient = new ApiClient();
RestEndPoint pageUrl;
while (true) {
pageUrl = getNextPageEndPoint();
if(pageUrl == null) {
throw new IllegalStateException("We have reached the end and the code isn't designed to handle the end here"); // we have reached the end
}
currentPageNumber++;
try {
resp = apiClient.failSafeGet(pageUrl, getRetryCount());
break;
}
catch (MalformedJsonException e) {
logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
for (Consumer<Integer> consumer: onSkipListenerList) {
consumer.accept(batchSize); // inform each listener that we are skipping this many entries
}
}
finally { // We need to set the next page end point no matter the outcome of the try catch. N.B. this gets executed even if there is a break
if(resp == null) {
// no next possible
setNextPageEndPoint(null); // don't consider next; we reached the max
this.thisPage = null;
} else {
if(currentPageNumber > maxPages - 1) {
// because a request has been made already, so reduce by 1
setNextPageEndPoint(null); // don't consider next; we reached the max
} else {
// else consider next page
setNextPageEndPoint(constructNextPageEndPoint(pageUrl, resp));
}
this.thisPage = this.parseResult(resp);
setTotalCount(resp.getInt("totalResults"));
}
}
}
}
EDIT I forgot to mention, that when I said it always evaluates to null, I meant that my IDE - Intellij IDEA, is warning me that the if condition always evaluates to null. The following is the help that shows up in Intellij (with Ctrl-F1).
Condition 'resp == null' is always 'true' less... (Ctrl+F1)
This inspection analyzes method control and data flow to report possible conditions that are always true or false, expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.
Variables, method parameters and return values marked as #Nullable or #NotNull are treated as nullable (or not-null, respectively) and used during the analysis to check nullability contracts, e.g. report possible NullPointerException errors.
More complex contracts can be defined using #Contract annotation, for example:
#Contract("_, null -> null") — method returns null if its second argument is null #Contract("_, null -> null; _, !null -> !null") — method returns null if its second argument is null and not-null otherwise #Contract("true -> fail") — a typical assertFalse method which throws an exception if true is passed to it
The inspection can be configured to use custom #Nullable
#NotNull annotations (by default the ones from annotations.jar will be used)
EDIT 2
As it turns out, the code analysis is wrong, the value is non-null once run. Thank you everyone (including commentators) for sharing your insights and advice. Ultimately I inserted a logger.info with the value before the condition and everything seemed to work. The reason it seemed to stop working is because the graph server was running into timeouts.
This is normal behaviour. This call
apiClient.failSafeGet(pageUrl, getRetryCount());
throws the exception, so the value assignment to resp is never completed so in the finally block the value is null. So, either you method is always throwing an exception, or, if not, it is returning null at some point.
In your code:
try {
resp = apiClient.failSafeGet(pageUrl, getRetryCount());
break;
}
catch (MalformedJsonException e) {
logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
for (Consumer<Integer> consumer: onSkipListenerList) {
consumer.accept(batchSize); // inform each listener that we are skipping this many entries
}
}
finally {.....
If resp = apiClient.failSafeGet(pageUrl, getRetryCount()); throws an exception, resp will be always null, because the program failed before assing the instance to resp.
So I don't want to avoid an IndexOutofBounds error; however, I want to know how to know when one hits it without crashing the program.
List<String> pool = new ArrayList<>();
pool.add("a");
boolean checked = (pool.get(1) == null); //I know this doensn't work
System.out.println(checked); //I want false
So in this example it is obvious that nothing exists in index 1 of my List pool. Is it possible to get a boolean value for this? Or is it possible to check if the end of a list has been reached without doing i < list.size()? Thanks for your time and help.
It's called a try-catch block:
boolean hasValue;
try {
hasValue = (pool.get(i) != null);
} catch (IndexOutOfBoundsException e) {
hasValue = false;
}
// hasValue == true if non-null value found at index i
However this is an anti-pattern called "exceptions as flow control".
The answer is no. You can check the docs and see that other than checking the size there is no way to "fetch if exists" or to find if "does index exist".
Trying to access the index and catching the exception is possible but not recommended because catching exceptions is an expensive operation in java
Okay, I have never had this problem before so I am not sure how to word it or to repair it, I am building a java application that creates dealers, in that application I have the parameters passed in to the DealerFactory.createDealer method and proceed to first check if that dealer exists with a conditional statement that looks like this:
if (DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId)) {
throw new Exception("Sorry That Dealer Already Exists");
} else if (DealerFactory.fetchDealer(loginId).getId().equals(DNo)){
throw new Exception("Sorry That Dealer Already Exists");
} else {
<< proceed with the rest of the method here >>
I have seen this done before so as to check the availability of the username and the id of the person being created. However after running it I found that if I create the dealer and the condition evaluates to true the if statement works just fine letting me know that I have created a user that already exists and I need to create him/her with new a different Id and username. However if the condition evaluates to false I never seem to make it into the else portion of the statement, I am getting no errors, no compilation issues, and no exceptions I have written the statement differently to try that, which wasn't really any different it just looked syntactically different:
if (DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId)
|| DealerFactory.fetchDealer(loginId).getId().equals(DNo)) {
throw new Exception("Sorry That Dealer Already Exists");
}
I have included println statements to follow the program through its run and when the condition evaluates to false I never make it into the else statement. I cant seem to figure out why it is breaking on the condition statement when it is evaluated to false, any thoughts?
edit:::
Ok so that I can be of more assistance in helping you guys help me lol here is the method in its entirety, I apologize for not posting it in the first place
public static int create(String DNo, String name, String admin,
String loginId, String password, String callSrc, String voiSys,
String whoCall, String callBrt, String active, String adfEmail)
throws SQLException, Exception {
int validateResult = 0;
if (DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId)
|| DealerFactory.fetchDealer(loginId).getId().equals(DNo)) {
throw new Exception("Sorry That Dealer Already Exists");
}
try {
DealerFactory.pool = DBConnector.getInstance();
DealerFactory.connect = DBConnector.getConnection();
DealerFactory.preparedStatement = connect
.prepareStatement("Insert Into Dealers (DNo, Dealer, Admin, Login, Password, CallSrc, VoiSys, WhoC, CBrt, Active, ADFemail) "
+ "values(?,?,?,?,?,?,?,?,?,?,?)");
DealerFactory.preparedStatement.setString(1, DNo);
DealerFactory.preparedStatement.setString(2, name);
DealerFactory.preparedStatement.setString(3, admin);
DealerFactory.preparedStatement.setString(4, loginId);
DealerFactory.preparedStatement.setString(5, password);
DealerFactory.preparedStatement.setString(6, callSrc);
DealerFactory.preparedStatement.setString(7, voiSys);
DealerFactory.preparedStatement.setString(8, whoCall);
DealerFactory.preparedStatement.setString(9, callBrt);
DealerFactory.preparedStatement.setString(10, active);
DealerFactory.preparedStatement.setString(11, adfEmail);
validateResult = DealerFactory.preparedStatement
.executeUpdate();
} catch (SQLException ex) {
System.err.println("Error: " + ex + "\n");
ex.printStackTrace();
} finally {
DBUtils.closePrepStatement(DealerFactory.preparedStatement);
DealerFactory.pool.freeConnection(DealerFactory.connect);
}
return validateResult;
}
First things first, you shouldn't chain methods like that due to dangers of NullPointerException
So this part:
if(DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId))
Could look something like this:
if(DealerFactory.fetchDealer(loginId) != null &&
DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId))
Or you could have a separate null check before all your if statements.
However, what you are doing is an overkill. This whole part:
DealerFactory.fetchDealer(loginId).getLoginId()
Returns null if you cannot find a dealer or loginId that you already have.
Assuming your fetchDealer() method returns null if dealer cannot be found.
Instead of:
if(DealerFactory.fetchDealer(loginId).getLoginId().equals(loginId)))
You can just do:
if(DealerFactory.fetchDealer(loginId) != null)
Another improvement you could do is to add a method to DealerFactory called dealerExists(String id) declared something like this:
boolean dealerExists(String id) {
return (YOUR_DATA_STRUCTURE_OF_DEALERS.get(id) != null);
}
Or even:
boolean dealerExists(String id) {
return (fetchDealer(loginId) != null);
}
This would allow for better logical flow of your code. Your if statement would be very clear then:
if(DealerFactory.dealerExists(loginId) {
throw new Exception("Sorry That Dealer Already Exists");
}
Also, the value DNo is the dealer number I presume and you are checking if a dealer exists with the provided loginId or the provided DNo. However, in you checks you are comparing the DNo to the loginId to check if a dealer exists. What exactly is the point of DNo and shouldn't the loginId be enough to determine that the dealer exists?
If you really need to check the DNo as well, just add it as a check within the methods I suggested above.
More information regrading the variables that you are passing into the conditional would be of great help, (i.e. loginId and DNo). The first thing I would do is simplify your conditions in the if & else if statements.
It seems like you could change the if conditional to be if(DealerFactory.fetchDealer(loginId)) and have it work just the same since if the factory returns a dealer with the ID that you are looking for, that dealer already exists. From my understanding of what you're trying to achieve, it's unnecessary to dig any deeper. Also try running through this section of code with the debugger and monitor variables step-by-step to see what things look like at each line of code.
Edit:
You could also move the expressions outside of the conditional and set them to variables. For example:
int dealerId = DealerFactory.fetchDealer(loginId);
if(dealerId != null && dealerId != loginId) {
//<< proceed with the rest of the method here >>
} else {
//<<throw exception>>
}
Checking to see if dealerId is null in the conditional would avoid NullPointerExceptions, and declaring things outside of the conditional will make it easier to debug by hand.