Java comparing enumerator (Strange behaviour) - java

I work with a Java project and Eclipse(Version 3.6.2) as IDE, in a enum comparison i get a strange behaviour, following an example of the weirdness :
Global Variable :
StatusType status = StatusType.SIGNATURE;
Code :
String trsStatus = "END";
if(trsStatus.equals("END") && (this.status.compareTo(StatusType.SIGNATURE) != 0)){
//Do something
}
This comparison succeeds and enter in the if block, Why ? In this case the second evaluation(this.status.compareTo(StatusType.SIGNATURE) != 0) of the if statements fail because the result is false ! Why java however enter in the block ???
If i evaluate the expression on the expression watcher of eclipse debugger the value of the statements are :
trsStatus.equals("END") ---> true
(this.status.compareTo(StatusType.SIGNATURE) != 0) ---> false
I've done another test, if i assign the result of the second expression in the if statements to a boolean variable :
boolean sign = (this.status.compareTo(StatusType.SIGNATURE) != 0);
i get this result :
(this.status.compareTo(StatusType.SIGNATURE) != 0) ---> false
sign ---> true
Why ?!?
How this can be possible ?

Could it be that StatusType overrides compareTo() in some weird way?
Are there any other threads that could be changing the value of the status field?
In any case, you should use equals() or even == rather than compareTo() here.

this.status.compareTo(StatusType.SIGNATURE) != 0 will return zero, because zero means they are equal. compareTo() returns either 1, -1, or 0, based on which value is considered greater.

The only sensible reason I could imagine is that
this.status != StatusType.SIGNATURE
Period. You probably set status to some other value unknowingly. Maybe with another thread. Who knows. What does status evaluate to, in your debugger?
In any case, there is certainly no such "bug" in Java. Unless you post some more code that proves it ;-)

You should use: this.status != StatusType.SIGNATURE.

public class Test {
public static void main(String[] args) {
TestEnum e = TestEnum.SIGNATURE;
System.out.println(e.compareTo(TestEnum.SIGNATURE));
String test = "test";
if (test.equals("test") && e.compareTo(TestEnum.SIGNATURE) != 0) {
System.out.println("I'm here");
}
}
}
I did the following test. It does not enter the if block and print "I'm here".
Can you post your snippet?

Related

Calling a method in the while loop condition

I'm curious is it possible to call a method that returns a boolean value in the condition part of a while loop?
As in:
while(someMethod()!= true){
//Do stuff
}
And the method simply returns a true or false. Is this possible or not and if so is there a correct syntax or a better way?
Edit: Thanks for the quick responses. As an extension to my question is it possible to call the method multiple times for different things but require them all to be the same before exiting the loop?
For example:
while(!(someMethod(input_a) == someMethod(input_b))){
//Do stuff
}
Where both of the returned values are the returned values are equal?
Hope this will help you
public boolean functionOne(int i){
// some operation
if(i == 1) return true;
else return false;
}
public void otherFunc(){
int i = 0;
if(functionOne(i)) { // e.g: if(functionOne(i) == true)
// your code
// 0!=1 so result is fort
}
if(!functionOne(i)){ // e.g: if(functionOne(i) == false)
// your code
// 0!=1 it is false, but ! before functionOne negate so ! of false is true
}
// **for your while**
while(functionOne(i)){ // while function returns true
// code
}
// **or**
while(!functionOne(i)){ // while function returns false
// code
}
}
Yes of course!
public static boolean someMethod(){
return false;
}
public static void main(String[] args){
while(!someMethod()){
//do something
System.out.println("Hi");
}
}
Like in this code, an infinite loop will be called if the method returns false, but if the method returns true, it will just come out of the while loop. :)
Less is best:
while (!someMethod()) {
// Do stuff
}
It's never a good idea to compare to a boolean result to a boolean literal. Prefer using the result in-line, using the logical unary not operator ! as required.
Answering the now-edited version of the question, less is still best:
while (someMethod(input_a) != someMethod(input_b))
You can find the specification of the while loop in JLS Sec 14.12:
The while statement executes an Expression and a Statement repeatedly until the value of the Expression is false.
WhileStatement:
while ( Expression ) Statement
WhileStatementNoShortIf:
while ( Expression ) StatementNoShortIf
The Expression must have type boolean or Boolean, or a compile-time error occurs.
So, you can use anything which is an Expression of type boolean (or Boolean).
And if you click through the productions in the language spec:
Expression, contains
AssignmentExpression, contains
ConditionalExpression, contains
ConditionalOrExpression, contains
ConditionalAndExpression, contains
InclusiveOrExpression, contains
ExclusiveOrExpression, contains
AndExpression, contains
EqualityExpression, contains
RelationalExpression, contains
ShiftExpression, contains
AdditiveExpression, contains
MultiplicativeExpression, contains
UnaryExpression, contains
UnaryExpressionNotPlusMinus, contains
PostfixExpression, contains
Primary, contains
PrimaryNoNewArray, contains
MethodInvocation
Phew! That's pretty deeply buried! (You can read this like an inheritance hierarchy, so every MethodInvocation is a PrimaryNoNewArray, and every PrimaryNoNewArray is a Primary etc).
So, transitively, every MethodInvocation is an Expression, hence it's fine to use it as the expression in a while loop.
Addressing your edit: yes, that's fine too. If you look at the detail of the EqualityExpression:
EqualityExpression:
RelationalExpression
EqualityExpression == RelationalExpression
EqualityExpression != RelationalExpression
As already described above, you can use an EqualityExpression as the Expression in a WhileStatement. And something of the form
RelationalExpression != RelationalExpression
is an EqualityExpression by the rule shown. Since all MethodInvocations are RelationalExpressions, you can use method invocations in the while statement as you've shown:
while(someMethod(input_a) != someMethod(input_b)) {
(a != b is an easier way of writing !(a == b)).
This is the way we have done loops over java iterators. For instance:
Iterator[String] iterator = util.Arrays.asList("One", "Two", "Three").iterator();
while(iterator.hasNext()) {
println(iterator.next());
}
We have also done something similar for the JDBC ResultSet interface.

Is using the order of evaluation to check for null values bad practice?

If I wish to perform two checks on a string, that it is not null, and that it is not 0 length, I could do this-
if(string != null) {
if(string.length() > 0) {
//Do something
}
}
Or I could do this
if(string != null && string.length() > 0) {
//Do something
}
As the first check is executed first, the second comparison doesn't happen and a NullPointerException isn't thrown.
Is the second method guaranteed to work in all cases? And if so, would it be considered bad practice to use it?
No, it is perfectly fine and guaranteed to work in all cases.
Reference from Java specification: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7
The one worth mentioning here: as you write such checks very often, it is advisable to put them into some dedicated helper method; such as:
static boolean doesStringContentContent(String value) {
or something alike.
And from an "improved" readability perspective, you might prefer coding that like
if (value == null) return false;
if (value.isEmpty()) return false;
return true;
But that doesn't matter too much - the important part is that you should not start copying around this check.
And finally, the one other possibility would to not return a boolean, but to have a
void checkStringHasContent(String value) {
which could throw a NullPointerException resp. some other thingy for an empty string.
you are using && (and) operator in second expression. and nested if condition in first expression. in both cases you will get same result. because &&(and) operator execute second condition if only if first condition is true.
basically you are doing same thing in different manner.

Is there any method in java which does the same thing as isset() in php?

Basically I have a if..else logic as below
if(request.getParameter("action")=="delete" && request.getParameter("action")!=null)
{
//delete operation
}
else
{
//update operation
}
But during update process "action" parameter do not get attached with URL and hence NullPoitnerException is thrown.
Any solution to fix it?
Thanks in advance!
If your request.getParameter(x) returns null when x is not set, you could simply swap the two conditions in your if-clause.
Thus
if(request.getParameter("action")=="delete" && request.getParameter("action")!=null)
would become
if(request.getParameter("action")!=null && request.getParameter("action")=="delete")
Since && is a short-circuit Boolean And in Java, this will cause the the second half of the statement to be executed only if the part before the && evaluates to true - thereby preventing your NullPointerException.
request.getParameter("action")=="delete" is a comparison with a string literal, though. You are most likely better off using .equals() instead.
In Java 8 you can do like this
Optional<String> paramOptional=Optional.ofNullable(request.getParameter());
paramOptional.ifPresent(param->{
//Do something with param
});
OR
String param =paramOptional.orElse("you else string");//if null then this string will be return

Why doesn't this if-statement short circuit?

I'm currently fixing a bug in someone else's Java code, but I cannot explain the bug. The code in question is the following if-statement:
if (locked && DEBUG_ENABLED
&& owner != null
&& (owner.equals(playerName) || subowner.equals(playerName))
&& handleCommand(playerName, message)) {
....
} else {
....
}
In which DEBUG_ENABLED is initialized as private static boolean DEBUG_ENABLED = false; and handleCommand functions like this:
public boolean handleCommand(String name, String msg) {
if(msg.equals("Command1")) {
....
} else if(msg.equals("Command2")) {
....
} ....
} else { // No matching command
return false;
}
return true;
}
What puzzles me is that even though DEBUG_ENABLED is set to false, the code still calls and executes the handleCommand function. I always thought this wasn't supposed to happen due to short circuiting.
The if-statement itself in total is still evaluated as false, since only the code inside the else-block in the first snippet is executed.
So, how come this if-statement is behaving like this? Is it failing to short-circuit, or do I misunderstand the principle, or is there something completely different wrong with this part of code? (Besides the missing null check for subowner that is, which is done outside of this part.)
It is not possible that the && operator fails to short-circuit. Were you using & perhaps? If not it means you have made some false assumptions that previous conditions before the last one were false.

Left-hand side of assignment must be a variable

I'm trying to call a boolean method in another class and Eclipse is reporting the above error on the second line in the following code:
CCR ccrFlags = new CCR();
if (ccrFlags.cBit() = set)
The method being called from the class called "CCR" is:
public boolean cBit() {
boolean set = false;
return set;
}
I imagine I'm probably going about this in an idiotic way and would be grateful for any advice. Thanks, Robert.
Comparison should use == (double-equal):
CCR ccrFlags = new CCR();
if (ccrFlags.cBit() == set)
in an if, the condition has to be always true or false.
your error is, that = only assigns the values, but it is not a logical operation which can be true or false.
So you have to use == in conditions.

Categories

Resources