== or equals when comparing final static fields - java

I've returned back to Java after a little break with C# and I'm already tired of writing stuff like a.equals(b) so I was wondering if is there a way to use the == operator without breaking my program.
Here's my situation:
public static class A {
public final static A STATIC_FIELD = new A(prop1, prop2);
public A method(int param){
return (param > 0.5) ? STATIC_FIELD : new A(prop1, prop2);
}
}
Now, can I replace equals with == in the following snippet since I'm referring to the same object or is it wrong?
....
private bool method(){
A aInstance = getAInstance();
int param = Math.Random();
return aInstance.method(param).equals(A.STATIC_FIELD);
}
....
And what if the STATIC_FIELD in a value taken from an enum?

This depends on what do you want to do.
If you need to check if this is exactly the same object, use the direct comparison. If you need to check if the object wraps the same content (like string or number), then .equals should be used.
Most common errors with these methods seem coming from string comparison, where .equals returns true if the strings have the same content but == only returns true if this is the same instance of string.

You should avoid == (ok, let's agree that you know it :-)), also in relation to singleton instances as you may "forget" later that it is created via singleton. But I will give you a hint. Instead of:
if ((var != null) && (var.equals(A.STATIC_FIELD)))
you may write:
if (A.STATIC_FIELD.equals(var))
just like many people do not realize that to compare strings they may use:
if ("static string".equals(varString))
You may also use java.util.Objects.equals to compare objects without all this checking nulls burden.

no you cant use == instead of equals() becuase when we use == in java we are actually comparing the memory address of the object , so if the method returns STATIC_FIELD then it will work properly as its a static object and the address will be same everywhere.
But when method will return new object of A then the address wont match even if the content is same within the class because the new A(param1, param2) insists JVM to create a new object at a different memory location

== checks if two objects are the same instance. If you want to check if two variables are holding the same instance (as they may well be if you are assigning your variables to class constants), == is fine to use. It also won't error if your variable happens to hold null, so it has that benefit over .equals().
Instances of an enum are always constant, and two different instances will never be equal, so == is fine to use for those too.

If you don't override the equals() method, equals() and == do the same thing, check the equality of the references. You can make the replacement in this case, since method() will return the same reference as A.STATIC_FIELD when it is true. See this answer.

Related

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)){...}

Is there a reason the java compiler cannot just substitute .equals for == when comparing objects?

In java we need to compare objects using .equals() instead of ==. But why can't the compiler do this for us? For example:
if (myString == myOtherString){
doSomething();
}
why cant the compiler go "oh, we're comparing objects!", and change it to this:
if (myString.equals(myOtherString))
Why do we do this manually?
Edit - Guys, I know the difference between == and .equals(). You can stop telling me how ignorant I am. My question was why not just substitute .equals() since its what you want 99% of the time. I have learned that there are cases where knowing if two objects are truly the same reference is useful.
The == operator and equals() often do quite different things. It's only the default implementation of equals() inherited from Object that reverts to using ==. (String is a good example: strings that are equal() are often not ==.) Also, the first example in your code will execute fine if myString is null, while the second will throw an exception.
Sometimes you really just want to know if two object references are to the same object, not whether they refer to objects that have "the same contents" (the meaning of which is usually what equals() implements). Automatically converting == to equals() would be a bad idea.
There is a difference. equals(Object) checks if two objects are equal - i.e., have the same state. The == operator checks if two references indeed point to the same object. It isn't a common usecase, but it definitely has its usages - e.g., to borrow from IdentityHashMap's documentation:
A typical use of this class is topology-preserving object graph transformations, such as serialization or deep-copying. To perform such a transformation, a program must maintain a "node table" that keeps track of all the object references that have already been processed. The node table must not equate distinct objects even if they happen to be equal. Another typical use of this class is to maintain proxy objects. For example, a debugging facility might wish to maintain a proxy object for each object in the program being debugged.
Is there a reason the java compiler cannot just substitute .equals for == when comparing objects?
Java uses both equals() and ==
When you use == to compare objects, you are comparing whether the 2 objects reference the same instance.
When you use .equals(), most of the time you will be comparing one or some of the attributes of the 2 objects. (Comparing the 2 objects' content)
Example for use of == in optimization
public boolean equals(square s){
if(this == s){ //If s and this object is the same instance
return true; //return true straight away, no further checking needed
}
return (this.length == s.getLength() && this.breadth == s.getBreadth());
}

What use does the == operator have for String?

In Java, if one is to check if two Strings are equal, in the sense that their values are the same, he/she needs to use the equals method. E.g. :
String foo = "foo";
String bar = "bar";
if(foo.equals(bar)) { /* do stuff */ }
And if one wants to check for reference equality he needs to use the == operator on the two strings.
if( foo == bar ) { /* do stuff */ }
So my question is does the == operator have it's use for the String class ? Why would one want to compare String references ?
Edit:
What I am not asking : How to compare strings ? How does the == work ? How does the equals method work?
What I am asking is what uses does the == operator have for String class in Java ? What is the justification of not overloading it, so that it does a deep comparison ?
Imagine a thread-safe Queue<String> acting as a communication channel between a producer thread and a consumer thread. It seems perfectly reasonable to use a special String to indicate termination.
// Deliberate use of `new` to make sure JVM does not re-use a cached "EOT".
private static final String EOT = new String("EOT");
...
// Signal we're done.
queue.put(EOT);
// Meanwhile at the consumer end of the queue.
String got = queue.get();
if ( got == EOT ) {
// Tidy shutdown
}
note that this would be resilient to:
queue.put("EOT");
because "EOT" != EOT even though "EOT".equals(EOT) would be true.
What use is there for it? Not much in normal practice but you can always write a class that operates on intern()-ed strings, which can then use == to compare them.
Why it isn't overloaded is a simpler question: because there is no operator overloading in Java. (To mess things up a bit, the + operator IS sort of overloaded for strings, which was done to make string operations slightly less cumbersome. But you can argue that's just syntactic sugar and there certainly is no operator overloading in Java on the bytecode level.)
The lack of an overloaded == operator made the use of the operator much less ambiguous, at least for reference types. (That is, until the point autoboxing/unboxing was introduced, which muddies the waters again, but that's another story.) It also allows you to have classes like IdentityHashMap that will behave the same way for every object you put into it.
Having said all that, the decision to avoid operator overloading (where possible) was a fairly arbitrary design choice.
The == operator compares the reference between two objects. For example, if String x and String y refers to two different things, then the == operator will show false. However, the String.equals() method compares not if they refer to each other, but if the values (ex. "Hello", "World", etc.) are the same.
// A.java
String foo1 = "foo";
// B.java
String bar1 = "foo";
All String literals realized at compile time are added to String Constant Pool. So when you have two different String declarations in two different classes, two String objects will not be created and both foo1 & bar1 refer to the same String instance of value foo. Now that you have same String reference in two different variables, you can just check if those two strings are equal just by using == which is fast because all it does is compare the bit pattern, where as in equals() method, each character is compared and is generally used for two different String instances but same content.
In fact, if you look at equals() implementation in String class, the first check they do is Reference comparison using == because they might seem as different instances to you, but if they're String literals or if they're interned by someone else already, then all you have is a Single reference in two variables.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
// remaining code
}
Also, == is not just for Strings, it's used to compare any two bit patterns, be it primitives or references
1."=="operation of comparison are the values of the two variables are equal, for a reference type variables is expressed by the two variables in the heap memory address is the same, namely the stack have the same content.
2."equals"Whether the two operation variables represent references to the same object in the heap, i.e. whether the contents of the same.
String s = "string1"; creates 1 reference and 1 object in pool String
s1 = "string1"; creates just 1 reference and points to what s is
pointing to.
s == s1 // true
String s2 = new String("string1"); creates 1 object in heap, one in
pool and one reference.
//Since, s2 is pointing to different object so,
s2 == s // false
s1 == s // false
Problem :
So, suppose We want to check, how many unique String object is created and stored in pool by the application while it is running,
We can have a singleton object which can have all the String references stored in an array.
From the previous examples of s, s1 and s2, finally for s and s1, 1 object is created and for s2, 1 object (in total 2).
//If we use equals method, all
s.equals(s1) // gives true
s1.equals(s2) // gives true
//So, number of references present in the array of singleton object will be our
//total number of objects created which equals to 3 // doesn't match actual
//count which is 2
we can use == to check for equality of reference, so if reference is equal, we will not increment our count of unique String object in pool, and for every non equal result, we will increment the count.
here,
for
s // count = 1
s1 == s // count remains same
s2 == s // false, so count = 1 + 1 = 2
//We get total number of unique String objects created and got stored in pool using ==
Simple answer...
Why would one want to compare String references ?
Because they want to compare String values in a very fast way.
Strings are not always interned(). String constants are, but it is possible that the string was created manually on the heap. Using the intern() on a manually created string allows us to to continue using reference comparison on our strings for value comparison.
What is the justification of not overloading it, so that it does a deep comparison ?
Because Java does not have operator overloading as a design decision
Operator '==' is a reference operator always, and equals() is a value method always. In C++ you can change that, but many feel that simply obfuscates the code.
Checking references is Faster compared to checking the entire Strings' equality.
Assume you have Large Strings (URLs or DBMS queries), a have multiple references to them. To check if they are equal, either you can check character by character or you can check if they both refer to the same object.
In fact, equals method in java first checks if the references are same and only if not goes ahead and checks character by character.
Java is full of references and hence, you might need a case where you need to check if two variables are referring to the same String/Object rather than both having each copy of the same String so that you can update string at one place and it reflects in all variables.
To do so, equals method does not help as it checks the copies to be equal as well. you need to check if they both refer to the same object and hence == comes into picture.
It seems that this was asked before and received quite a popular answer here:
Why didn't == operator string value comparison make it to Java?
The simple answer is: consistency
I guess it's just consistency, or "principle of least astonishment".
String is an object, so it would be surprising if was treated
differently than other objects.
Although this is not the fundamental reason, a usage could be to improve performances: before executing a heavy computation, "internalize" your Strings (intern()) and use only == for comparisons.
What I am asking is what uses does the == operator have for String class in Java ?
What is the justification of not overloading it, so that it does a deep comparison ?
== and equals have altogether different uses.
== confirms if there is reference-equality
Equals confirms if the objects contains are same.
Example of reference-equality is IdentityHashMap.
There could be a case in which Only the object inserting something to IdentityHashMap has the right to get/remove the object.
overloading reference-equality can lead to unwanted complexity for java.
for example
if (string)
{
do deep equality
}
else
{
do reference-equality
}
/*****************************************************************/
public class IdentityHashMap extends AbstractMap implements Map, Serializable, Cloneable
This class implements the Map interface with a hash table, using reference-equality in place of object-equality when comparing keys (and values). In other words, in an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2). (In normal Map implementations (like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).)
This class is not a general-purpose Map implementation! While this class implements the Map interface, it intentionally violates Map's general contract, which mandates the use of the equals method when comparing objects. This class is designed for use only in the rare cases wherein reference-equality semantics are required.

What does the word "equals" mean in Java API?

I'm not sure anyone will know the answer to this question, unless you are responsible for writing the Jave API, but when the Java API says "equals", does it always mean that a.equals(b) evaluates to true, or sometime does it mean a == b is true? I have recently extended a class and wondered if I needed to override a method depending on where or not it used == or .equals. Specifically, I extended javafx.beans.binding.ObjectExpression and was curious about the .isEqualTo(Object other) method. I checked the source (here) and found that this method uses .equals for comparison. I'm curious if I can be confident that when I read things like
"Creates a new BooleanExpression that holds true if this ObjectExpression is equal to a constant value."
that the method is not using the == operator. Although, as I think of it, the API can't possibly mean .equals either, since (for example)
String constant = "constant";
ObjectExpress<String> stringExpression = new MyStringExpression("constant");
constant.equals(stringExpression)
will always evaluates to false. So maybe my question should be "when the API says 'equals', does it always refer to the most reasonable way to apply .equal or sometime does it refer to the analogous way to apply ==?"
EDIT
I think based on the answers I should clarify: this is not a question about the difference between == and .equal. It is about to which the Java API is referring when it uses the English word "equals".
It's clear that you do understand the difference between equals() and ==. So your question is rather philosophical :)
Generally, many APIs use "equals to" in the meaning of equals() and "is the same as" in the meaning of ==. E.g. JUnit has assertion method assertEquals() and assertSame().
However, use your common sense and analyze the language of the doucmentation. Notice in your quoted sentence from API the usage of the indefinite article:
"Creates a new BooleanExpression that holds true if this
ObjectExpression is equal to a constant value."
"a constant value" clearly means any constant value, not the same value as the "constant" value. So it is clear that this cannot mean the same as constant.equals(stringExpression).
So take it in this way: when documentation says "equals", take it that it relates to the content of the variable, not to its reference. But use common sense and read the sentence as a whole :)
Does it answer your question? :P
does it always mean that a.equals(b) evaluates to true, or sometime
does it mean a == b is true?
when the API says 'equals', does it always refer to the most
reasonable way to apply .equal or sometime does it refer to the
analogous way to apply ==?"
It's about overriding equals() method, In java, only += operator overloaded, other operators can't be overloaded means, you can't override ==
When writing an API-doc when using the term "equal" this should usually mean "equal in terms of the equals()-method". If it really does depends on the thoroughness of the writer of the documentation, but in the official API-docs I would always take as having this meaning.
For your question "can it also mean ==": it can in the way that Object's equals()-method just checks for reference-identity, that is it checks using ==.
If you use .equals it will compare the value. By using == you are comparing the reference and these doesn't have to be the same even if your values are the same.
See following website for a full explanation: http://www.javabeat.net/what-is-difference-between-equals-and/
I've copied a part of his example:
s1 = new String("abc");
s2 = new String("abc");
Now, if you use the equals() method to check for their equivalence as
if(s1.equals(s2))
System.out.println("s1.equals(s2) is TRUE");
else
System.out.println("s1.equals(s2) is FALSE");
You will get the output as TRUE as the equals() method check for the content equality.
Lets check the == operator..
if(s1==s2)
System.out.printlln("s1==s2 is TRUE");
else
System.out.println("s1==s2 is FALSE");
Now you will get the FALSE as output because both s1 and s2 are pointing to two different objects even though both of them share the same string content. It is because of new String() everytime a new object is created.
When some one creates a java class it inherit boolean equals(Object o) method from class 'Object', as all user defined class when not extending any other class extends class Object implicitly.
When this class is instantiated using new operator the equality of this objects are achieved by using this underline formula.
return (this == obj);
Hence it will return true if and only if both object refers to the same object on the heap i.e (a == b) = true
class Abc{}
Abc a = new Abc();
Abc b = a;
a==b //(true)
a.equals(b) //(true)
And suppose they are instance of same class but are two different object than
class Abc{}
Abc a = new Abc();
Abc b = new Abc();
a==b; //(false)
a.equals(b); //(false)
But when an class created overrides this equals method then this equality is evaluated using the new formula provided while overriding it. for example .equals object override by java.util.Date
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
This will return true if and only both Date object have equal value returned by getTime() method.
Hope this helps. Feel free to ask further questions if any doubt.

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

Categories

Resources