How to prevent null check before equals - java

I find stuff like this rather annoying and ugly in equals methods:
if (field == null)
{
if (other.field != null)
return false;
}
else if ( ! field.equals(other.field))
return false;
In C# I could've done this:
if( ! Object.Equals(field, other.field))
return false;
Is there something similar in Java, or what is the preferred way to do this kind if thing?

Java 7 offers java.util.Objects.equals.

Use commons-lang:
org.apache.commons.lang.ObjectUtils.equals(Object object1, Object object2)
Source code:
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
From Apache
http://commons.apache.org/lang/
That's about equivalent to what you do in C#

Guava equal which does this :
public static boolean equal(#Nullable Object a, #Nullable Object b) {
return a == b || (a != null && a.equals(b));
}
or null object pattern
Guava also has the somewhat related comparison chain and a load of other goodies.

I would write it this way:
return field != null && other.field != null && field.equals(other.field);
which is not as elegant as the C# code line, but much shorter then the if tree you posted.

I accept all answers technically. Practically I will not use any of them in code I have under control because all provided solutions are working around the core problem: null-values. KEEP YOUR CORE MODEL FREE FROM NULL VALUES, and the question is obsolete in this case.
At system borders like third party libraries one has to deal with null values sometimes. They should converted into meaningful values for the core model. There the given solutions are helpful.
Even if Oracle recommends the equals-Methods to be null-safe, think about that: Once you accept null values your model it is getting fragile. The equals-method will not be the last method where you will check for null. You have to manage null-checks in your method call hierarchy. Methods may not be reusable out of the box anymore. Soon, every parameter will be checked for null.
I saw both sides:
On one side code full of null checks, methods that trust not a single parameter anymore and developers that are afraid to forget a null check.
On the other side code with full expressive statements that make clear assertions to have full functioning objects that can be used without fear of NullPointerExceptions.

As part of the Project Coin, there was a proposal for adding a series of null-safe operators to Java. Sadly, they didn't make it into Java 7, maybe they'll appear in Java 8. Here is the general idea of how they would work

Actually everyone follows there own way to do this and also i would like to introduce groovy here.
There is one way
field == null ? false : true; // So basically it will return true when it is not null.
In groovy there is null safe operator for objects. Lets take an example for class
A {
String name = "test1"
String surName = "test2"
public String returnName() {
return name + surName
}
}
A a = null
a?.name
// Mentioned operator ? will actually check whether a is null or not. then it will invoke name.
Note: i didn't applied semi colon in code as this is not require in groovy.

String.valueOf() will solve some of those problems if the toString is implemented for your classes. It will spit out the toString() answer or "null" if the pointer is null.

Use == operator when you are checking for object references, if both the references refers same object it will return true. Otherwise if you are looking for object content then go with .equals method of objects.
So null means it doesn't have any memory location given in heap. So it can be simply checked with '==' operator.

Related

Java: Standards to use constant.equals(variable) [duplicate]

If I try to do a .equals() on a null string in java, a null pointer exception will be thrown. I am wondering, if I am trying to compare if a string is equal to some constant string, can I do the following:
MY_CONSTANT_STRING.equals(aStringVariable)
I know it will work, but is this just really poor code?
This is a standard Java idiom jokingly called a Yoda condition.
Personally I prefer to handle the null case explicitly, but the Yoda way is used a lot and any experienced Java programmer should be able to understand what is going on immediately. It's fine to use.
is this just really poor code?
No, this is the way many people would code the statement to avoid NPE.
What you've got is fine. It's even possible to use a String literal.
if( "value".equals(variable) ) {
...
If you don't like that, you can always explicitly check for null and equality, and combine the two checks with &&. The short circuiting of the operator will make sure you never get a NPE.
if( (variable != null) && variable.equals("value") ) {
...
I would keep the "CONSTANT.equals(possibleNull)" code without the null test only if it is a normal condition that the variable could be null - for instance because it just came out of a property map.
Similarly you can get away with not checking for null in instanceof-checks - like:
Food dinner = map.get("dinner");
if (dinner instanceof Soup) {
((Soup)blah).eat();
} // We don't care if it is a Fish or null
But if you really did not expect null, you should explicitly check for that in a separate if-test, and handle it appropriately. It's generally better to catch such data errors early rather than later.
Nope, it's usually done to avoid NPE. However, I usually prefer to do explicit check for null.
If you are concerned about the quality of your code, write a helper class that takes care of equality test:
public class ObjectHelper {
public static boolean testEquality(Object o1, Object o2) {
if (o1 == null && o2 == null) return true;
if (o1 == null) return false;
return o1.equals(o2);
}
}
Then use it like this:
if (ObjectHelper.testEquality(aStringVariable, My_CONSTANT_STRING))
Your so-called constant MIGHT stop being constant. It might be read from a configuration file some time in the future.

Is there any benefit to use methods of Objects.java? [duplicate]

This question already has an answer here:
Purpose of Objects.isNull(...) / Objects.nonNull(...)
(1 answer)
Closed 4 years ago.
I examined methods of Objects.java, but i couldn't find too much useful sides of that methods. For Example the code that will work when i use Objects.isNull :
public static boolean isNull(Object obj) {
return obj == null;
}
There are the two ways for checking nullity of two objects :
if(o == null)
if(Objects.isNull(o))
So there are not so many differences between them. Another example the code that will work i use Objects.toString
public static String toString(Object o) {
return String.valueOf(o);
}
When i use it It calls toString of object at background.(With only one difference it writes "null", if the object is null because it uses String.valueOf()
And Objects.equals :
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
It will makes null check in every check(without knowing it is necessary or not.)
Am i wrong? If i am, why should i use that methods and other methods of Objects.java?
EDIT
I did not asked this question only for Objects.isNull and Objects.nonNull, i want to know purpose, usability(except for lambdas also) and benefits of Objects class and its methods. But in javadoc is written that only for Objects.isNull and Objects.nonNull have purpose to use with lambdas(as predicate filter(Objects::isNull)). I want to know others as well.
Objects.isNull(), and the more useful Objects.nonNull(), exist for the purpose of being used in lambda expressions. Objects.toString() was introduced for null safety (as pointed out by #davidxxx), but is also very useful in lambdas.
For example, list.stream().filter(Objects::nonNull).map(Objects::toString) will give you a Stream<String> with the results of calling toString() on all the elements in list that are not null.
Objects.equals() is useful precisely when you know that the objects you're comparing might be null, as it saves you some typing.
You seem to be asking 3 separate questions, so I'll address them separately:
isNull() and its companion nonNull() were added in Java 8 to be used as method references, similarly to Integer.sum() and Boolean.logicalOr(). For example:
// Print only non-null elements
list.stream()
.filter(Objects::nonNull)
.forEach(System.out::println);
I don't see any advantage in calling Objects.toString() over String.valueOf(). Maybe it was included for uniformity with the other null-safe helpers.
If you know the objects are non-null, go ahead and use Object.equals(). Objects.equals() is meant to be used when they might both be null.
In some cases some of these methods don't bring a "great" value and you can suitably ignore them.
1) But as you manipulate classes that miss some checks (check null to prevent NullPointerException) or "optimization" (check first reference equality in equals() for example) , using these Objects methods allow to not be hurt by these and so to
keep your client code robust without writing directly all these checks.
2) Another interesting use is for lambda body as you want to use a method reference
3) At last, it allows to make homogeneous the way to perform these very common processings.
These 3 processing rely on 3 different ways :
String.valueOf(o);
if(o == null){...}
a.equals(b);
While these rely on a single way : utility methods defined in Objects.
Objects.toString(o);
if(Objects.isNull(o)){...}
if(Objects.equals(a, b)){...}

Why does comparing enums using == cause a PMD warning?

The following compares two enum values using ==:
MyEnum enum1 = blah(); // could return null
MyEnum enum2 = blahblah() // could return null
if (enum1 == enum2) {
// ...
}
But PMD gives a CompareObjectsWithEquals warning on line 3:
Use equals() to compare object references
Not sure I understand the source code for this check but thought it was OK to compare two enums using == so am wondering whether my code could be improved or the check is incorrect.
This is indeed accepted as bug:
http://sourceforge.net/p/pmd/bugs/1028/
http://sourceforge.net/p/pmd/bugs/909/
However, it seems to be tricky to catch all possible cases (quote from the newer bug):
That one is a bit tricky, as in order to determine, whether a type is
a Enum, we need type resolution.
I was able to adjust the rule to check, whether the type of the
variables is an Enum. This works only, if the Enum types are on the
"auxclasspath" of pmd, so that the type resolution can find it.
Your example in isolation would still trigger this false positive, as
PMD doesn't know what ProcessingStatus is. I verified it with
java.math.RoundingMode, which is always on the classpath and will be
resolved.
("Your example" refers to the ticket author, not the OP on Stack Overflow)
Your case might work with PMD 5, the source you linked belongs to PMD 4.
Update: The current source contains the additional check for enums:
// skip, if it is an enum
if (type0.getType() != null && type0.getType().equals(type1.getType()) && type0.getType().isEnum()) {
return data;
}
It's fine to use .equals(), because under the hoods, what happens is that the instances are compared with ==.
public final boolean equals(Object other) {
return this==other;
}
Note that this implementation of .equals() is final, which means you cannot override it in your enum.

Simple if statement problem

I am trying to return a toString if something is true.
I have this code:
public void printoutsailings() {
for (Sailing s:sailings) {
String hamburg = ("Hamburg");
if ((s.getDeparturePort()) == hamburg) {
System.out.println(s.toStringAdjusted());
}
}
}
However I get nothing when I run the method (when I should be getting something). I assume that I have somehow messed up the logic or not understood =,== and eq properly, I'm not too sure.
There is nothing wrong with the toString or the for loop, and I'm not getting any compiler or run time errors. It's just that the logic is wrong.
If someone could put me right that'd be appreciated. Thanks.
You should be using .equals() instead of == to check String equality. Try the following:
if ((s.getDeparturePort()).equals(hamburg)) {
System.out.println(s.toStringAdjusted());
}
In short, == checks to see if two strings are the exact same reference, and .equals() checks to see if two strings look the same.
It should also be said that you need to use .equals() for checking the equality of any Object type, not just strings. Only primitive types (int, double, char) should use == for equality.
To compensate for the fact that the departure might be null, simply switch the condition around. It would read - hamburg.equals(s.getDeparturePort())
Yup, you're relying on == comparing for equality rather than identity. Change the code to:
if (s.getDeparturePort().equals("hamburg")) {
System.out.println(s.toStringAdjusted());
}
For reference types, == in Java always means "compare the two references for equality". In other words, it returns whether two references refer to the same object.
You want to check whether the two strings are equal instead - i.e. whether they contain the same sequence of characters. That's what the overridden equals method is for.
(To give a real-world demonstration of this, I catch a number 36 bus every morning. To me those buses are equal because they take me on the same route, but I know there are several number 36 buses - I don't get on the exact same physical bus every day.)
Note that the code above will throw a NullPointerException if s.getDeparturePort() returns null. There are two ways of avoiding this. First, you can use a known-to-be-non-null reference as the target of the method call:
if ("hamburg".equals(s.getDeparturePort()))
Alternatively, you can perform an explicit nullity check:
String port = s.getDeparturePort();
if (port != null && port.equals("hamburg"))
Or you can leave it to throw an exception, if that's the most appropriate behaviour (i.e. if you really don't expect getDeparturePort() to return null, and want to blow up if you get such bad data rather than continuing and possibly propagating the problem).
You must compare strings using equals method.
In Java, String is a reference type. It means that your String hamburg, pointing to a variable in the stack, contains a reference to a managed heap object actually containing the string. A value type, conversely, is completely allocated into the stack.
The ==, read reference equals compares the stack values. Instead, all classes implement an equals method that is read value compare. It compares the real values of the object wherever they are allocated in.
The following code works for you:
public void printoutsailings() {
for (Sailing s:sailings) {
String hamburg = ("Hamburg");
if (hamburg.equals(s.getDeparturePort())) { //First hamburg to prevent any possible NullPointerException
System.out.println(s.toStringAdjusted());
}
}
}
Just for your curiosity:
PHP only compares by value
C# redefines the == operator as a value equals operator, but only for the string class
In VB.NET, the default = operator is the value equals operator. The Is operator corresponds to the reference equals
In String, equality is checked either by equals() method or compareTo() method.
Your solution can be fixed by:
if (s.getDeparturePort().equals(hamburg)) {
System.out.println(s.toStringAdjusted());
}
To avoid receiving a null from s.getDeparturePort(), I would do the following.
if ("Hamburg".equals(s.getDeparturePort())) {
System.out.println(s.toStringAdjusted());
}
This is to avoid NullPointerException if s.getDeparturePort() is null (from your example code).
Alternatively, you can use the compareTo() method like so....
Your changed code (to using compareTo():
if (s.getDeparturePort().compareTo(hamburg) == 0) {
System.out.println(s.toStringAdjusted());
}
My alternate solution (using compareTo())
if ("Hamburg".compareTo(s.getDeparturePort()) == 0) { //Zero means that it is equal.
System.out.println(s.toStringAdjusted());
}
Btw...
String hamburg = ("Hamburg");
can be easily written as
String hamburg = "Hamburg";
if(hamburg.equals(s.getDeparturePort()))
Try
public void printoutsailings() {
for (Sailing s:sailings) {
String hamburg = "Hamburg";
if (s.getDeparturePort().equals(hamburg)) {
System.out.println(s.toStringAdjusted());
}
}
}
== is comparing the object itself, you're better off using .equals() as it will compare the actual value of the String, such as :
if ((s.equals(hamburg)) {
System.out.println(s.toStringAdjusted());
}
Also make sure that Sailings has at least 1 value, otherwise you'll never enter that for loop anyway
Instead of simply providing the code...check this out, I am almost certain it will get you to where you need to go...
try if (s.getDeparturePort().equals(hamburg))
Instead of using == for String objects (or any objects), use .compareTo(), as in this example:
http://leepoint.net/notes-java/data/strings/12stringcomparison.html

Highlight when equality operator (==) is used for string comparisons in Eclipse

Is there any way I can get Eclipse to highlight the use of the == operator to test String equality? I keep mistakenly using it instead of calling .equals().
I'd really like to make that into a warning and require an #SuppressWarnings annotation to remove it, in the yet-to-happen case that I actually want to compare strings for object equality.
Are there any tools can I use to help break this bad habit at edit-time?
Use a static analysis tool such as FindBugs, PMD, or CheckStyle.
There are Eclipse plugins for each, along with Ant tasks, Maven plugins, etc.
Each of these has rules relating to String equality (Findbugs rule, PMD rule, Checkstyle rule).
The obvious answer to the question has already been given, but here is a warning that is not a direct answer: obj.equals can also fail if obj is null. So you'll often have to use code like this:
if(mystr1 != null && mystr1.equals(mystr2))
because this
if(mystr1.equals(mystr2))
would fail with a NullPointerException if mystr1 is null.
Which is why, when the comparison string is a known constant, the following syntax is often used:
if("ABCDEF".equals(mystr1))
rather than
if(mystr1.equals("ABCDEF"))
For this reason, many libraries (like apache commons / lang ) provide utility functions that combine these checks:
// this is the definition of org.apache.commons.lang.StringUtils.equals(String, String)
public static boolean equals(String str1, String str2) {
return str1 == null ? str2 == null : str1.equals(str2);
}
// this is the definition of org.apache.commons.lang.ObjectUtils.equals(Object, Object)
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
Using these methods is usually safer than plain equals, unless you know for sure that one of the two objects is not null
I disagree with previous answers - it is a bug in eclipse and you can vote for it here : https://bugs.eclipse.org/bugs/show_bug.cgi?id=39095.
Eclipse can very well warn you when you compare Strings with == as this is seldom what you wanted (or what the original author wanted).

Categories

Resources