Lazy evaluation not working as it should - java

I had to evaluate a boolean expression frecuently, so I converted it in a private method in it's class. Here is the code it's causing me trouble:
//"x", "y" and "team" are already defined
return (map.isWalkable(x,y) &&
(!map.isOccupied(x,y) || map.getOccupant(x, y).getTeam() == team) );
Methods should be preety much self-explanatory as for the purpose of this question. Now, isWalkable and isOccupied both return a boolean, and getOccupant is the only method returning an object reference. The problem is that I'm getting a NullPointerException when executing this piece of code, and that shouldn't be happening because isOccupied returns true if and only if map.getOccupant != null (that's actually what that method returns). So with a language supporting lazy boolean evaluation from left to right (as I assume java is, or at least that's what I was able to read) the getOccupant method should never be executed whenever it would return null am I right?
Is this more compiler-dependent than I thought it was? Should it be safer if I used if statements, or is there simply something obvious I'm missing here, maybe operations get resolved the other way round.

The issue is your parenthesis. Try
return (map.isWalkable(x,y) && (!map.isOccupied(x,y) || map.getOccupant(x, y).getTeam() == team));

Simply put, no, lazy evaluation is not broken. Your code is.
Either map is null, or map.getOccupant(x,y) returns null.
If you put them on their own lines and go through them with a debugger, you'll notice that "oh no, I was so stupid and didn't notice that".
The compiler, JVM or anything else has nothing to do with this.

Related

Do if statements that call methods on an object modify the object?

I'm trying to perform actions on my object, but only do so if certain things are true. I have several methods which is consider "action" methods, they do some action that attempts to modify the object and returns true/false if that action can be done.
Example 1
Thing thing = new Thing();
if (thing.changeSomething()){
if (thing.shouldDoSomething()){
//do more things
}
}
I know about compound boolean expressions like to check if a number in a valid range of values
if(number>0 && number<=10)
//number is valid
But haven't really done much when the sub-expressions are method calls
Example 2
if ( thing.changeSomething() && (thing.shouldDoSomething() ){
//do more things
}
Is Example 2 the same as Example 1?
Will Example 2 call the shouldDoSomething() method? Because I don't want this to happen because sometimes shouldDoSomething() actually has other implications & changes other aspects of the object.
Calling
if (thing.changeSomething()){
if (thing.shouldDoSomething()){
is esentially equivalent to
if (thing.changeSomething() && thing.shouldDoSomething()){
I guess they are translated to the exact same IL.
However as mentioned in the comments the second method is only executed if the first one evaluates to true. If the first operand of an &&-operator is already false there´s no need to execute the second also, so your shouldDoSomething-method isn´t executed if changeSomething allready returned false.
Btw. this applies to both Java and C#.
In Java, the logical AND operator && is a short circuit operator, meaning the right side is not evaluated if the result of the expression can be determined solely from the left operand. Specifically, if the left side evaluates to false, the whole expression is false and the right side does not need to be evaluated to determine that.
In the case of your function calls:
if ( thing.changeSomething() && (thing.shouldDoSomething() ){
//do more things
}
If thing.changeSomething() returns false then thing.shouldDoSomething() will not be called since the expression evaluates to false regardless of what this function may return. So yes, the above is equivalent to:
if ( thing.changeSomething() ) {
if (thing.shouldDoSomething() ){
//do more things
}
}
The simple answer and what it comes down to is, it depends on if the thing.changeSomething() method returns a boolean. It is going to create problems if it does not. It is very possible to define this method to do something and return true after it does what it was supposed to do. In which case the second example would work.
If it does not return boolean you should see an error or it might not work to your liking.
It should call the method when to do it that way in example 2. What I would recommend because you don't want that is to create getter() and checker() methods that you use to get info on the object without having to change it. This can also be done with data fields, depends on class structure.
Hope this is more digestible and helps!

Is using return at the start of method bad coding practice?

I have found myself using the following practice, but something inside me kind of cringes every time i use it. Basically, it's a precondition test on the parameters to determine if the actual work should be done.
public static void doSomething(List<String> things)
{
if(things == null || things.size() <= 0)
return;
//...snip... do actual work
}
It is good practice to return at the earliest opportunity.
That way the least amount of code gets executed and evaluated.
Code that does not run cannot be in error.
Furthermore it makes the function easier to read, because you do not have to deal with all the cases that do not apply anymore.
Compare the following code
private Date someMethod(Boolean test) {
Date result;
if (null == test) {
result = null
} else {
result = test ? something : other;
}
return result;
}
vs
private Date someMethod(Boolean test) {
if (null == test) {
return null
}
return test ? something : other;
}
The second one is shorter, does not need an else and does not need the temp variable.
Note that in Java the return statement exits the function right away; in other languages (e.g. Pascal) the almost equivalent code result:= something; does not return.
Because of this fact it is customary to return at many points in Java methods.
Calling this bad practice is ignoring the fact that that particular train has long since left the station in Java.
If you are going to exit a function at many points in a function anyway, it's best to exit at the earliest opportunity
It's a matter of style and personal preference. There's nothing wrong with it.
To the best of my understanding - no.
For the sake of easier debugging there should be only one return/exit point in a subroutine, method or function.
With such approach your program may become longer and less readable, but while debugging you can put a break point at the exit and always see the state of what you return. For example you can log the state of all local variables - it may be really helpful for troubleshooting.
It looks like there a two "schools" - one says "return as early as possible", whereas another one says "there should be only one return/exit point in a program".
I am a proponent of the first one, though in practice sometimes follow the second one, just to save time.
Also, do not forget about exceptions. Very often the fact that you have to return from a method early means that you are in an exceptional situation. In your example I think throwing an exception is more appropriate.
PMD seems to think so, and that you should always let your methods run to the end, however, for certain quick sanity checks, I still use premature return statements.
It does impair the readability of the method a little, but in some cases that can be better than adding yet another if statement or other means by which to run the method to the end for all cases.
There's nothing inherently wrong with it, but if it makes you cringe, you could throw an IllegalArgumentException instead. In some cases, that's more accurate. It could, however, result in a bunch of code that look this whenever you call doSomething:
try {
doSomething(myList);
} catch (IllegalArgumentException e) {}
There is no correct answer to this question, it is a matter of taste.
In the specific example above there may be better ways of enforcing a pre-condition, but I view the general pattern of multiple early returns as akin to guards in functional programming.
I personally have no issue with this style - I think it can result in cleaner code. Trying contort everything to have a single exit point can increase verbosity and reduce readability.
It's good practice. So continue with your good work.
There is nothing wrong with it. Personally, I would use else statement to execute the rest of the function, and let it return naturally.
If you want to avoid the "return" in your method : maybe you could use a subClass of Exception of your own and handle it in your method's call ?
For example :
public static void doSomething(List<String> things) throws MyExceptionIfThingsIsEmpty {
if(things == null || things.size() <= 0)
throw new MyExceptionIfThingsIsEmpty(1, "Error, the list is empty !");
//...snip... do actual work
}
Edit :
If you don't want to use the "return" statement, you could do the opposite in the if() :
if(things != null && things.size() > 0)
// do your things
If function is long (say, 20 lines or more), then, it is good to return for few error conditions in the beginning so that reader of code can focus on logic when reading rest of the function. If function is small (say 5 lines or less), then return statements in the beginning can be distracting for reader.
So, decision should be based on primarily on whether the function becomes more readable or less readable.
Java good practices say that, as often as possible, return statements should be unique and written at the end of the method. To control what you return, use a variable. However, for returning from a void method, like the example you use, what I'd do would be perform the check in a middle method used only for such purpose. Anyway, don't take this too serious - keywords like continue should never be used according to Java good practices, but they're there, inside your scope.

Java: Use getter vs caching value

I have a getter that returns a String and I am comparing it to some other String. I check the returned value for null so my ifstatement looks like this (and I really do exit early if it is true)
if (someObject.getFoo() != null && someObject.getFoo().equals(someOtherString)) {
return;
}
Performancewise, would it be better to store the returned String rather than calling the getter twice like this? Does it even matter?
String foo = someObject.getFoo();
if (foo != null && foo.equals(someOtherString)) {
return;
}
To answer questions from the comments, this check is not performed very often and the getter is fairly simple. I am mostly curious how allocating a new local variable compares to executing the getter an additional time.
It depends entirely on what the getter does. If it's a simple getter (retrieving a data member), then the JVM will be able to inline it on-the-fly if it determines that code is a hot spot for performance. This is actually why Oracle/Sun's JVM is called "HotSpot". :-) It will apply aggressive JIT optimization where it sees that it needs it (when it can). If the getter does something complex, though, naturally it could be slower to use it and have it repeat that work.
If the code isn't a hot spot, of course, you don't care whether there's a difference in performance.
Someone once told me that the inlined getter can sometimes be faster than the value cached to a local variable, but I've never proven that to myself and don't know the theory behind why it would be the case.
Use the second block. The first block will most likely get optimized to the second anyway, and the second is more readable. But the main reason is that, if someObject is ever accessed by other threads, and if the optimization somehow gets disabled, the first block will throw no end of NullPointerException exceptions.
Also: even without multi-threading, if someObject is by any chance made volatile, the optimization will disappear. (Bad for performance, and, of course, really bad with multiple threads.) And lastly, the second block will make using a debugger easier (not that that would ever be necessary.)
You can omit the first null check since equals does that for you:
The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
So the best solution is simply:
if(someOtherString.equals(someObject.getFoo())
They both look same,even Performance wise.Use the 1st block if you are sure you won't be using the returned value further,if not,use 2nd block.
I prefer the second code block because it assigns foo and then foo cannot change to null/notnull.
Null are often required and Java should solve this by using the 'Elvis' operator:
if (someObject.getFoo()?.equals(someOtherString)) {
return;
}

Object null-ness check in Java

Which one is recommended and to be used to check the Object null-ness?
null != Object
or
Object != null
and other way
null == Object
or
Object == null
...and is there any difference between them?
(In)equality is commutative, so there is no difference.
Historically the former stems from C to avoid accidentally assigning a value in a conditional statement, however that mostly applies to ==, not !=. Also Java requires the condition in a conditional statement to have a boolean value, so the only place where it could go wrong nowadays would be
if (a == false) ...
if you accidentally omit one of the =. A rare case, I guess (though probably not so much, given what students frequently write in their first two terms). Joonas also points out another (more obscure) case in the comments.
It's always more readable to use
Object != null
because that reads as "the object is not null", which is literally what the condition is.
The only case where you want to swap the two is to avoid accidentally using
Object = null
which will return true even though it is not the desired behavior, when you wanted to say
Object == null
but in reality not only do modern tools catch these kinds of mistakes, but wide use of the reverse can actually be an impediment to anyone who has to read the code.

Java : "xx".equals(variable) better than variable.equals("xx") , TRUE?

I'm reviewing a manual of best practices and recommendation coding java I think is doubtful.
Recomendation:
String variable;
"xx".equals(variable) // OK
variable.equals("xx") //Not recomended
Because prevents appearance of NullPointerException that are not controlled
Is this true?
This is a very common technique that causes the test to return false if the variable is null instead of throwing a NullPointerException. But I guess I'll be different and say that I wouldn't regard this as a recommendation that you always should follow.
I definitely think it is something that all Java programmers should be aware of as it is a common idiom.
It's also a useful technique to make code more concise (you can handle the null and not null case at the same time).
But:
It makes your code harder to read: "If blue is the sky..."
If you have just checked that your argument is not null on the previous line then it is unnecessary.
If you forgot to test for null and someone does come with a null argument that you weren't expecting it then a NullPointerException is not necessarily the worst possible outcome. Pretending everything is OK and carrying until it eventually fails later is not really a better alternative. Failing fast is good.
Personally I don't think usage of this technique should be required in all cases. I think it should be left to the programmer's judgement on a case-by-case basis. The important thing is to make sure you've handled the null case in an appropriate manner and how you do that depends on the situation. Checking correct handling of null values could be part of the testing / code review guidelines.
It is true. If variable is null in your example,
variable.equals("xx");
will throw a NPE because you can't call a method (equals) on a null object. But
"xx".equals(variable);
will just return false without error.
Actually, I think that the original recommendation is true. If you use variable.equals("xx"), then you will get a NullPointerException if variable is null. Putting the constant string on the left hand side avoids this possibility.
It's up to you whether this defense is worth the pain of what many people consider an unnatural idiom.
This is a common technique used in Java (and C#) programs. The first form avoids the null pointer exception because the .equals() method is called on the constant string "xx", which is never null. A non-null string compared to a null is false.
If you know that variable will never be null (and your program is incorrect in some other way if it is ever null), then using variable.equals("xx") is fine.
It's true that using any propertie of an object that way helps you to avoid the NPE.
But that's why we have Exceptions, to handle those kind of thing.
Maybe if you use "xx".equals(variable) you would never know if the value of variable is null or just isn't equal to "xx". IMO it's best to know that you are getting a null value in your variable, so you can reasign it, rather than just ignore it.
You are correct about the order of the check--if the variable is null, calling .equals on the string constant will prevent an NPE--but I'm not sure I consider this a good idea; Personally I call it "slop".
Slop is when you don't detect an abnormal condition but in fact create habits to personally avoid it's detection. Passing around a null as a string for an extended period of time will eventually lead to errors that may be obscure and hard to find.
Coding for slop is the opposite of "Fail fast fail hard".
Using a null as a string can occasionally make a great "Special" value, but the fact that you are trying to compare it to something indicates that your understanding of the system is incomplete (at best)--the sooner you find this fact out, the better.
On the other hand, making all variables final by default, using Generics and minimizing visibility of all objects/methods are habits that reduce slop.
If you need to check for null, I find this better readable than
if (variable != null && variable.equals("xx")). It's more a matter of personal preference.
As a side note, here is a design pattern where this code recommendation might not make any difference, since the String (i.e. Optional<String>) is never null because of the .isPresent() call from the design pattern:
Optional<String> gender = Optional.of("MALE");
if (gender.isPresent()) {
System.out.println("Value available.");
} else {
System.out.println("Value not available.");
}
gender.ifPresent(g -> System.out.println("Consumer: equals: " + g.equals("whatever")));

Categories

Resources