What is the correct way to implement compareObjects() - java

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.

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.

Java Multiple comparision in java

Pardon me if this is a stupid question.. I was wondering if there is any support for following comparison in Java:
(a, b, c .... != null) in place for :
(a != null && b != null && c != null && d ! null and so on ..)
I was trying to make code more readable as my code which is almost unreadable due to multiple condition in single statement.
code :
variable = (rest.host != null && rest.payload != null
&& rest.lockQueue != null && rest.endpoint != null ) || rest.default.setState
|| rest.scheduler.locked && rest.scheduler.queue.isFull()
&& lastPayload.getActivity.status.executing ? onExecute(rest.payload) : wait(TIME);
If your elements are in a collection, use collection.stream().allMatch(x -> x != null). Actually, there's even a predicate for that: collection.stream().allMatch(Objects::nonNull).
If your elements aren't in a collection, you can still use Arrays.asList() to create an ad-hoc list from them. So, in your case:
Arrays.asList(rest.host, rest.payload, rest.lockQueue, rest.endpoint).stream().allMatch(Objects::nonNull)
EDIT: actually, as someone mentioned in another answer, there is a method that creates a stream directly, namely Stream.of(...). So:
Stream.of(rest.host, rest.payload, rest.lockQueue, rest.endpoint).allMatch(Objects::nonNull)
You could do something like this to make sure everything is not null, if using a Java version lower than 8. Otherwise I would go with the other people's answers using streams.
private boolean checkIfNotNull( Object ... objects ) {
for(int i = 0; i < objects.length; i++) {
if(objects[i] == null)
return false;
}
return true;
}
and you could pass in all the objects that you want to check if they are null.
then you can call this in the if statement such as
if( checkIfNotNull( a, b, c, d, e, f, g ) ) {
//do stuff
}
In java 8, it could be done as next Stream.of(a, b, c, d).allMatch(Objects::nonNull), it will return true if they are all non null.
I think if you want your code more readable, you should replace your comparisons with method calls that "says" what each comparison is.
Example:
if (isAllRight(a, b, c)) {
...
}
In other cases you can break them into single comparisons and check one by one:
if (a == NUL) {
return false;
}
if (b == NULL) {
return false;
}
return true;

boolean recursion part 2

trying to write a boolean function that returns true if 'm' is a ancestor of the current class. 'm' is an ancestor if it is a mom or dad, or a ancestor of mom or dad.
will this get me there?
public boolean isAncestor(member m){
if (mom == m || dad == m){
return true;
}
else{
if(isAncestor(m.mom) || isAncestor(m.dad)){
return true;
}
}
return false;
}
thanks!
Yes, more or less. What if you get to a layer of the ancestry where mom or dad aren't known, and are null?
public boolean isAncestor(member m){
if (m == null)
return false;
if (mom.equals(m) || dad.equals(m))
return true;
else if(isAncestor(m.mom) || isAncestor(m.dad))
return true;
return false;
}
The logic will get you there, however one must take care with the equal signs.
In Java == compares for equality of instances. Odds are good that over time you will have two instances which are comparatively equal but exist in different instances. If your code has been written to prevent such a thing from occurring, then you don't need to change the == to .equals(...); but, if you didn't put in any safeguards to ensure only one instance of each "same" object exists, then you might want to change the comparison to .equals(...) and implement an custom "public boolean equals(Object other) {...}` method for the base "person" class.
If you're going to use recurrsion, you are going to need to have a stop condition. Does everyone have a mom or a dad? consider this:
public boolean isAncestor(Member m) {
// stop condition
if(this.mom == null && this.dad == null) return false;
// stop condition
if(this.mom == m || this.dad == m) return true;
// loop condition
return mom.isAncestor(m) || dad.isAncestor(m);
}
It might but it is not 100% correct. You should also check if mum and dad exist otherwise you might end up with NullPointerException.
Moreover the others are correct with the == usage, quite suspicious.
When does the recursion stop, if there is no relationship?
Actually, you need a way to know which two members you are comparing for relationship. You'll probably want to do something like this (untested):
/**
* #param m1 the member we want to get ancestry from
* #param m2 the member we presume is an ancestor
*/
public boolean isAncestor(member m1, member m2){
if (m1 == NULL || m2 == NULL) {
return false;
}
if (m1.isMom(m2) || m1.isDad(m2)){
return true;
}
else if(isAncestor(m1.mom, m2) || isAncestor(m1.dad, m2)) {
return true;
}
return false;
}
You'd need to write isMom and isDad to compare the relationship of m2 to m1.

Difference between these two appraoch in calling equals method?

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.

Equality comparison -- any saner way?

How do I implement this equality comparison is a sane java way?
boolean x = (a == b) || (a.equals(b))
I want to make sure the content of both objects is equal but null is also ok, i.e. both can be null and are thus equal.
Update: just to be clear, I have to implement this comparison several times and don't want to copy&paste this stuff every time, especially with lenghty object names. With 'a' and 'b' it looks small and simple, but tends to grow... I'd like to know if I'm missing some existing Java feature for this.
You might want to have a look at the always useful Apache Commons Lang, more precisely ObjectUtils.equals().
Another way to do
boolean x = null==a ? null==b : a.equals(b);
The typical pattern is:
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
// Now deal with a and b, knowing that they are non-identical, non-null references
Yes, it's wordy - but if you separate it out into its own method, you can keep it under reasonable control.
What happens if a is null but b is not? I think you really want:
boolean x = (a == null && b == null) || (a != null && a.equals(b))
EDIT: You could implement a static NullEquals method for the class that takes two objects of that class and does the comparison as above to avoid rewriting and make the code a little cleaner.
public class MyClass {
public static boolean NullEquals( MyClass a, MyClass b )
{
return (a == null && b == null) || (a != null && a.equals(b));
}
}
if (MyClass.NullEquals(a,b))
{
...
}
Not a direct answer, but if you have lot of objects that can be or not null, may be that indicates some problem with your code. Take a look at the Null Pattern , that is an alternative way to represent the absence of an object
What about:
boolean x = equals( a, b );
public static boolean equals( Object a, Object b ) {
if ( a == null && a == b ) {
return true;
} else {
return a == b || a.equals( b );
}
}
Let me see.
if a is null and a is b then it's ok
if a is not null then if a == b ( same ref ) return true by shortcircuit
if a is not b ( 2dns part of the OR probably b is null ) then return a ( not null ) .equals( b ) whatever b is
Yeap covered.
Can not add comment,
Treat this as comment to Jon Skeet's answer.
Does Null = Null true or false in Java.
More specifically what should be Null = Null should be treated and How and why the different language treat this case ?
The most common way of doing it is:
a==null ? b==null : a.equals(b)
A potentially slightly more efficient, but less clear, expressions is:
a==b || (a!=null && a.equals(b))
You can of course put this inside a method:
public static boolean eq(Object a, Object b) {
return a==b || (a!=null && a.equals(b));
}
Note the original question code NPEs if a is null and b is non-null.
For performance reasons, usually it is good to check for identity before executing any other logic, as was done in the question. However, many of the answers don't take this into account.
The best place to put the identity check is in the implementation of the equals method on your class:
public boolean equals(Object obj) {
if(this == obj) return true;
...
}
If this has/can be done, you can do the comparison easily:
a == null ? b == null : a.equals(b);
Otherwise you might have to check for identity yourself:
a == null ? b == null : (a == b || a.equals(b));

Categories

Resources