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.
Related
How can I JUnit test the last block of this equal?
Any help would be much appreciated. This is the method in question:
#Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
//unreachable block
ServiceOrderRelationship serviceOrderRelationship = (ServiceOrderRelationship) o;
return Objects.equals(this.id, serviceOrderRelationship.id) &&
Objects.equals(this.href, serviceOrderRelationship.href) &&
Objects.equals(this.relationshipType, serviceOrderRelationship.relationshipType) &&
Objects.equals(this.baseType, serviceOrderRelationship.baseType) &&
Objects.equals(this.schemaLocation, serviceOrderRelationship.schemaLocation) &&
Objects.equals(this.type, serviceOrderRelationship.type) &&
Objects.equals(this.referredType, serviceOrderRelationship.referredType);
}
This is what I've been doing but I can never reach the last block of code inside the equals method:
#Test
public void testEquals() throws Exception {
assertFalse(serviceOrderRelationship.equals(null));
assertTrue(serviceOrderRelationship.equals(serviceOrderRelationship));
assertFalse(serviceOrderRelationship.equals(serviceOrderRelationship1));
}
First of all, thank you all for your responses!
This is how I was able to reach the last block of the equals method. I had to initialize both objects di and di1 and set every variable to the same value, then test the equals condition switching back and forth one variable at a time to a different value. This is an example from another POJO:
// Initialize objects
di.setEdgeId("edgeId");
di.setIdentityEndpoint("identityEndpoint");
di.setUsername("username");
di1.setEdgeId("edgeId");
di1.setIdentityEndpoint("identityEndpoint");
di1.setUsername("username");
// Change value of var and test equal
di1.setEdgeId("edgeIdm");
assertFalse(di.equals(di1));
di1.setEdgeId("edgeId");
// same
di1.setIdentityEndpoint("identityEndpointm");
assertFalse(di.equals(di1));
di1.setIdentityEndpoint("identityEndpoint");
// Same
di1.setUsername("usernamem");
assertFalse(di.equals(di1));
di1.setUsername("username");
// Then at the end perform the other tests
assertTrue(di.equals(di));
assertTrue(di.equals(di1));
assertFalse(di.equals(null));
assertFalse(di.equals(42));
Your problem might be that one of the follow cases, in which the method would return prematurely.
If serviceOrderRelationship and serviceOrderRelationship1 are references to the same object, the true would be returned. Similarly, if they are not of the same type, false would be returned. If serviceOrderRelationship1 is null, false would be returned.
If serviceOrderRelationship is null, then calling equals on it would throw a NullPointerException.
i am confused because I need my array to be equal to the other array but I don't know how to compare them without losing their values
If both roots are null you will get an undesired result based on what you're trying to do with your second if condition.
It looks like if both roots are null you want to return true, but you're returning false. You could use just one if statement
if(thisRoot == null || otherRoot == null){
return thisRoot == null && otherRoot == null;
}
You have a bigger problem with how you're comparing the data of the two nodes.
thisRoot.getData() != otherRoot.getData()
This comparison is not what I think you're looking for. Instead you should overrride the equals method for your data objects and compare using it instead
The order of your conditions causes a problem.
if (thisRoot == null || otherRoot == null) {
return false;
}
if (thisRoot == null && otherRoot == null) {
return true;
}
The first condition will evaluate to true (and lead to return false) even if both branches are null.
You should first evaluate if both branches are null; after that, you can check the case where only one of them is null.
I have the following code in a class used to simulate the IRS with employer filings in accordance with the filer. I am required to override the equals class but I keep getting the error saying that the methods I am trying to use cannot be found when called on the casted Object.
#Override
public boolean equals(Object obj) {
if ((this == null )|| (obj == null) || (this.getClass() != obj.getClass()))
return false;
if ((this.sameEmployer((Employer)obj))
&& (this.getEmployeeSSN() == (Employer)obj.getEmployeeSSN())
&& (this.getName() == (Employer)obj.getName())
&& (this.getEmployeeName() == (Employer)obj.getEmployeeName())
&& (this.getEmployeeWages() == (Employer)obj.getEmployeeWages()))
return true;
else
return false;
}
Casting happens after method calls. According to the precedence of operators, () for method calling is at the highest level, 1, while () for casting is at level 3. In other words you are attempting to cast obj.getEmployeeSSN() as an Employer, not obj.
Once you know obj is an Employer, you can place parentheses to force casting first, e.g.
&& (this.getEmployeeSSN() == ((Employer) obj).getEmployeeSSN())
However, it looks like a mess of parentheses. For clarity, just declare an Employer variable, cast it once, then call the methods, passing the Employer variable.
Employer emp = (Employer) obj;
if (this.sameEmployer(emp)
&& ...
For expressions like this:
(Employer)obj.getEmployeeSSN()
The . has higher precedence - "binds tighter" - than the cast. So it's closer to:
(Employer) (obj.getEmployeeSSN())
... whereas you want:
((Employer) obj).getEmployeeSSN()
in order to cast and then call the method. That's most easily done by casting in an earlier line:
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
Employee other = (Employee) obj;
// Now use "other" in the rest of the code:
return sameEmployer(other)
&& getEmployeeSSN() == other.getEmployeeSSN()
...;
}
Note that:
this can never be null, so you don't need to test it
You don't need nearly as many brackets as you had before
I'd strongly encourage you to use braces for all if blocks... you'd be surprised at how easy it is to end up with mistakes otherwise. (There are lots of SO questions which are basically due to that...)
Any time you have:
if (foo) {
return true;
} else {
return false;
}
you should simplify it to:
return foo;
Class Object doesn't have getEmployeeSSN(). What you should have instead is :
(this.getEmployeeSSN() == ((Employer)obj).getEmployeeSSN() //and so forth.
The cast should happen first, then you try to use the method on the casted object
You just have a problem with priority of your operations. The cast to (Employer) will happen after you call the specific methods. To enforce the priority you need to add brackets:
((Employer) obj).getName()
instead of
(Employer) obj.getName()
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.
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.