Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SonarQube bugs #1060

Merged
merged 2 commits into from May 9, 2023
Merged

SonarQube bugs #1060

merged 2 commits into from May 9, 2023

Conversation

tmrpavan
Copy link
Contributor

Avoid Comparing Integers in Java using == Operator

image

@tmrpavan
Copy link
Contributor Author

@aalhossary Can you please review this PR

@josemduarte
Copy link
Contributor

I think auto-unboxing takes care of this in most cases. For instance if I rewrite your first test as:

Integer m = 1;
Integer n = 1;
System.out.println(m==n);

The output is true

@josemduarte
Copy link
Contributor

Interestingly this doesn't work:

Integer m = new Integer(1);
Integer n = new Integer(1);
System.out.println(m==n);

but this works:

Integer m = Integer.valueOf(1);
Integer n = Integer.valueOf(1);
System.out.println(m==n);

@aalhossary
Copy link
Member

aalhossary commented Apr 17, 2023

@josemduarte That is because of the internal implementation of valueOf()
It first tries to find a cached/cachable value of the parameter in a static HashTable of Integer. If found, it returns that statically cached object.
new Integer on the other hand, creates a new object in all cases.
UPDATE: autoboxing uses valueOf() under the hood.

Therefore, checking the equality of two autoboxed wrappers using == is safe within a range (as far as I remember in the range [-127, 128]).

However, the situation in this pull request (and the previous one) is actually about "not equal".

@tmrpavan
Copy link
Contributor Author

comparison rather than equality comparison. When using the "not equal" operator (!=) to compare two autoboxed Integer values, the result is not guaranteed to be correct, even within the range you mentioned.

This is because the "not equal" operator first unboxes the Integer values into primitive int values and then compares those values. If the two Integer values being compared happen to be in the cached range, they will be the same object reference and thus have the same primitive value. However, if they are not in the cached range, they will be different object references even if they have the same primitive value, and the "not equal" comparison will return false when it should have returned true.

To avoid this issue, it's recommended to use the equals() method for comparing two autoboxed Integer values instead of the "not equal" operator, as it compares the values of the objects rather than their references.

@tmrpavan
Copy link
Contributor Author

@aalhossary See the implementation on Objects.equals();

It first compares the objects with == operator.
1-> If bother are in cached range if both are same the first expression return true.
2-> If any one of the object is not in cached range if first expression return is flase for some case that case only it is going to check the values.

I hope using equals method safe.

public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
I
equals ion Integer class
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

@tmrpavan
Copy link
Contributor Author

@aalhossary
Is there any side effects using Objects.equals(). As per you previous post -> #1052 (comment) it gives expected results for all the scenarios.

@aalhossary
Copy link
Member

@tmrpavan using Objects.equals() instead of Integer.equals() (and instead of == of course) does the right job.

@aalhossary
Copy link
Member

aalhossary commented Apr 18, 2023

@josemduarte Now both this PR and #1052 address the same issue (i.e. duplicates).
What shall we do? close the old one and review the new one, or close the new one and ask the old one OP for modifications?

@tmrpavan
Copy link
Contributor Author

@aalhossary Any update on this

@josemduarte
Copy link
Contributor

Now both this PR and #1052 address the same issue (i.e. duplicates).
What shall we do? close the old one and review the new one, or close the new one and ask the old one OP for modifications?

Since #1052 has gone quiet (specially from the PR creator side). Let's close that one in favour of this. Still we'll want to review this PR of course.

Copy link
Member

@aalhossary aalhossary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments on your modifications

@tmrpavan
Copy link
Contributor Author

tmrpavan commented May 7, 2023

I am working on this

@tmrpavan
Copy link
Contributor Author

tmrpavan commented May 7, 2023

@aalhossary Modified as per the comments

Copy link
Member

@aalhossary aalhossary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you!

@aalhossary aalhossary merged commit 88b51de into biojava:master May 9, 2023
1 check passed
@tmrpavan tmrpavan deleted the tmrpavan-master branch May 10, 2023 17:00
@tmrpavan tmrpavan changed the title Sonar S4973 '==' and '!=' should not be used when 'equals' is overrid… SonarQube bugs May 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants