Difference between these two appraoch in calling equals method? - java

Approach one.
if (graphType.equals("All") || graphType.equals("ALL"))
Aprroach two.
if ("All".equals(graphType) || "ALL".equals(graphType))
What is the difference between these two approaches?
Why the below one is better?

The second one is better, as if graphType is null, the first code snippet will throw a NullPointerException.
Note that you can simplify your code using "ALL".equalsIgnoreCase(graphType) (if you accept values such as AlL or aLL...)
Edit regarding your comment:
If graphType is null, in the first case, you will get a NullPointerException. In the second case, the evaluation of the equals method will be false, as "someString".equals(null); always returns false:
Here is the code of the String.equals(String) method:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
(source)
The interesting line is if (anObject instanceof String) {. When you call the instanceof statement on a null object, this test always returns false. That's why "anyString".equals(null); will return false.

I feel the need to present a contrarian viewpoint to the accepted answer:
The first one is better, precisely because it will throw a NullPointerException in the case where graphType is null.
Generally, if an unexpected condition is found, you want to halt and throw an Exception as early as possible, otherwise you may continue to execute the program in an invalid state and the bug may become fiendishly difficult to track down.
This is sometimes referred to as the "fail-fast" principle.

romaintaz answer is absolutely correct. However, if you're like me, you might prefer to use the first approach to make your code easier to read. This is where assertions come into play:
assert graphType != null : "graphType is null";
if (graphType.equals("All") || graphType.equals("ALL"))
The question is whether your users will find a creative way to make graphType = null once you've finished testing.
The other thing I don't like about the second approach is that it fails silently in the case that graphType is unexpectedly null -- It prevents a runtime error, but may present a bug that's difficult to track down.

Related

Check if two objects are not equal, unless they are both null

The following Java snippet of code confuses me a bit. The method is trying to check whether two objects are NOT equal, using the standard .equals() method to denote that they are equal. Additionally, a boolean can determine whether two null's are considered equal or not. I'm wondering if:
The boolean logic in this method is indeed correct?
the return statement in the middle block can be omitted somehow. Could this logic be rewritten in a more concise or other way, maybe dropping the empty return, but keeping a high level of human readability of the code?
Snippet:
public static void verifyVariableIsNotEqualTo(Object variable, Object otherVariable, boolean considerBothNullAsEqual)
{
if(considerBothNullAsEqual && variable == null && otherVariable == null)
{
throw new Exception("not allowed to be equal");
}
if(variable == null || otherVariable == null)
{
return;
}
if(variable.equals(otherVariable))
{
throw new Exception("not allowed to be equal");
}
}
Yes, the logic in the method is correct. It throws the exception if the two objects are equal. You could remove the second condition and combine it with the third one, but I don't see much point. If you did, the method might look like this.
public static void verifyVariableIsNotEqualTo(Object variable, Object otherVariable, boolean considerBothNullAsEqual) throws Exception
{
if(considerBothNullAsEqual && variable == null && otherVariable == null)
{
throw new Exception("not allowed to be equal");
}
if(variable != null && variable.equals(otherVariable))
{
throw new Exception("not allowed to be equal");
}
}
Note that there's no need to check whether otherVariable is null separately, since the equals method on variable should return false if otherVariable is null.
There's an even more concise way to write this, but it's not worth considering, since it sacrifices readability.

Ternary operator evaluating conditional statement while condition not met

I have written some code; here the relevant snippets:
#NonNullByDefault
public class Score<NUMERAL, LITERAL>
{
protected NUMERAL value;
#Nullable
protected LITERAL literal;
[...]
I have overwritten my equals()method as follows:
#Override
public boolean equals(#Nullable Object object)
{
if(object == null) return false;
if(object == this) return true;
if( object instanceof Score)
{
return ((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
literal == null ? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null : literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral());
}
return false;
}
Basically, the idea is that a Score may only have a numeric value in which case the literal is null. I have written some unit tests and get a null pointer exception with the code below:
[....]
Score<Float, String> score = new Score<>(0.0f);
Score<Float, String> anotherScore = new Score<>(1.0f, "One");
[....]
assertFalse(score.equals(anotherScore));
If I am not mistaken, shouldn't short-cutting in equals prevent anything after the && from being executed as the first expression is already false? Furthermore, why the exception? As the conditional is true, I would expect the expression of the ternary to be evaluated and the conditional expression skipped. From what I have read in the specifications, this should be the behaviour. Furthermore, I found this question: Java ternary (immediate if) evaluation which should lend some more leverage to my thought process.
Maybe I have overlooked something rather obvious but I am out of ideas. Maybe you can help?
It short-circuits alright, but not quite the way you want it to. && has a higher precedence than the ternary ?: - therefore this (indentation, line breaks and comments added to clarify)
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
actually means this:
//the first line as a whole is the condition for ?:
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) && literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral())
This means, in practice, that if the first part of the condition is false but literal is null, you automatically enter the : part of the expression where you call literal.equals, causing the NullPointerException.
The fix is simple: add parentheses to tell Java which way you want stuff to be evaluated:
((Score<NUMERAL, LITERAL>) object).getValue().equals(value) &&
(literal == null
? ((Score<NUMERAL, LITERAL>) object).getLiteral() == null
: literal.equals(((Score<NUMERAL, LITERAL>) object).getLiteral()))

Broken function even though it appears to be correct

I've been testing my app today and somehow a function broke after I've done a completely unrelated change, and most importantly I can't see why it shouldn't work.
Here it is:
public static int componentStrId(String string)
{
for(int i = 0; i < GameMain.ComponentNames.length; i++)
{
Gdx.app.log("GameCoordinator", "componentStrId index: " + i);
if(string == GameMain.ComponentNames[i])
{
return i;
}
}
return -1;
}
Before you ask, yes, the string I feed it is present in the array I search from, and yet the function returns -1. It just cycles pointlessly through the array.
I've got the feeling that Eclipse freaked out, although maybe I'm just blind and can't see an obvious mistake... So what is it, the former or the latter?
Instead of this ...
if(string == GameMain.ComponentNames[i])
Use this ...
if(string.equals(GameMain.ComponentNames[i]))
If you provide
GameMain.ComponentNames[3]
as parameter it would return 3.
If you construct a String separately it would always return -1, as == would return true only if both references point at the same object.

What is the correct way to implement compareObjects()

I have compareObjects method implemented as below
public static int compareObjects(Comparable a, Comparable b){
if (a == null && b == null){
return 0;
} else if (a == null && b != null){
return -1;
} else if (a != null && b == null){
return 1;
} else {
return a.compareTo(b);
}
}
When I run this through findBugs, I get this suggestion on the line return a.compareTo(b):
There is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can't ever be executed; deciding that is beyond the ability of FindBugs. Due to the fact that this value had been previously tested for nullness, this is a definite possibility.
At this point a can never be null. Why does FindBugs show me this suggestion? How can I correct this; what is the correct way to implement compareObjects()?
I think it might be because you don't need the extra && statements. After the first if statement you already know that one of them is null.
public static int compareObjects(Comparable a, Comparable b){
if (a == null && b == null){
return 0;
} else if (a == null){
return -1;
} else if (b == null){
return 1;
} else {
return a.compareTo(b);
}
}
Looking at it again , try this code:
if (a == null && b == null){
return 0;
}
if (a == null){
return -1;
}
if (b == null){
return 1;
}
return a.compareTo(b);
It may be a limitation in FindBugs; I agree that you've covered all the bases, but your null-check is split across two different conditions. Now these conditions happen to be complementary, so at least one of them will fire if a is null, but depending how sophisticated FindBugs is, it may not recognise this.
Two options here, then:
Just ignore the FindBugs warning. Due to its nature it will raise some false positives from time to time, so don't feel like you have to rewrite your code to make it 100% happy if you don't think the rewrite is worthwhile on its own merits.
You can use the #SuppressWarnings annotation to actually communicate this to FindBugs, if you want the report to show a nice big zero at the end. See this question for an example.
Restructure the condition so that the nullity check on a is more explicit, by nesting if blocks:
if (a == null) {
return b == null ? 0 : -1;
}
return b == null ? 1 : a.compareTo(b);
Depending on your tastes and style that might be a better rewrite anyway, in that is more clearly says "if a is null, do this calculation and return it, otherwise do this calculation". You can of course change the ternary condition into another if-else block if you prefer that.

Logical mistake or not?

I have written this function which will set
val=max or min (if val comes null)
or val=val (val comes as an Integer or "max" or "min")
while calling i am probably sending checkValue(val,"min") or checkValue(val,"max")
public String checkValue(String val,String valType)
{
System.out.println("outside if val="+val);
if(!val.equals("min") && !val.equals("max"))
{
System.out.println("Inside if val="+val);
try{
System.out.println("*Inside try val="+val);
Integer.parseInt(val);
}
catch(NumberFormatException nFE)
{
System.out.println("***In catch val="+val);
val=valType;
}
return val;
}
else
{
return val;
}
}
But the problem is if val comes null then
outside if******val=null
is shown.
Can any1 tell me is this a logical mistake?
And why will I correct?
If val is null, then the expression val.equals("min") will throw an exception.
You could correct this by using:
if (!"min".equals(val) && !"max".equals(val))
to let it go inside the if block... but I would personally handle it at the start of the method:
if (val == null) {
// Do whatever you want
}
Btw, for the sake of readability you might want to consider allowing a little more whitespace in your code... at the moment it's very dense, which makes it harder to read.
...the problem is if val comes null then outside if****val=null is shown. Can any1 tell me is this a logical mistake?
The output is correct; whether you want it to come out that way is up to you.
Your next line
if(!val.equals("min") && !val.equals("max")){
...will throw a NullPointerException because you're trying to dereference val, which is null. You'll want to add an explicit check for whether val is null:
if (val == null) {
// Do what you want to do when val == null
}
you should use valType instead of val to check either minimum or maximum is necessary to check.
My advice to you in such cases to use boolean value or enum instead of strings. Consider something like that:
/**
* check the value for minimum if min is true and for maximum otherwise
*/
public String checkValue(String val, boolean min){
if (min) {
// ...
} else {
// ...
}
}
If you need to compare strings against constants you should write it the other way around to make it null-safe:
if (! "min".equals(val))
And while this is mostly a style issue, I would make all method arguments final and not re-assign them (because that is confusing), and you can also return from within the method, not just at the end. Or if you want to return at the end, do it at the very end, not have the same return statement in both the if and the else branch.

Categories

Resources