29

While comparing two values in Java, how do you test if both, the type and the value, are equivalent?

I know in JavaScript === can be used to accomplish this, so I tried that in Java, but it didn’t work.

I know this is a simple question, but I tried looking it up and I couldn’t find out what it was.

Scott Johnson
  • 288
  • 2
  • 12
JavaCakes
  • 361
  • 1
  • 3
  • 9
  • 6
    `a.equals(b)` with a properly written `equals` method. – luk2302 Jun 20 '19 at 11:42
  • In JavaScript, `===` can not be used to test if both, the type and the value, are equivalent. `var obj_a = {1: 2}; var obj_b = {1: 2}; console.log(obj_a === obj_b); // result is false` – LiuXiMin Jun 24 '19 at 04:41
  • @LiuXiMin I think it only doesn’t work with objects, but it does with everything else – JavaCakes Jun 24 '19 at 04:52
  • @JavaCakes No. `===` means `strictly equal` in JavaScript. You can not use it for objects, arrays, functions. Look [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Identity) for more details. – LiuXiMin Jun 24 '19 at 05:02
  • Well everything other than those, then – JavaCakes Jun 24 '19 at 08:00
  • 2
    The below answer more or less gives an explanation, but I'd say don't compare apples to oranges :) In fact, the closest analogy I can think of `===` in Java is actually `.equals()` if you're comparing `String`s or Numbers (`Integer` to `Integer` or `Double` to `Double`), but for primitives and other reference types, it is `==`, but if comparing `Integer` to `Double` (different boxed types), then no equivalent. Bottom line, try to grasp how each operator works in the specific language you're using. Drawing analogies between the two differing languages will likely be more confusing than helping. – M A Jun 24 '19 at 20:09

9 Answers9

49

TL;DR

In Java there is not such a comparison operator: ===, but == or equals

A longer explanation

In weakly typed languages such as JavaScript you can use the strict comparison operator (===) because the language allows comparison between variables which have different types.

For example, in JavaScript, you won't get a compile error if you do this:

var x = 10;
var y = 'foo';
console.log(x == y); // false

And it is useful, when you want to compare variables which may hold values that are "equals" but may be of different types.

For example

var x = 10;
var y = '10';
console.log(x == y)  // true
console.log(x === y) // false

In strongly typed languages such as Java, you don't need to use a strict comparison operator because the language already "handles" the type comparison.

For example:

int x = 10;
String y = "10";
System.out.println("10" == y); // true
System.out.println(x == y);    // compile error : Incompatible operand types int and String

So, basically, in Java, there is no need for checking for strictness using === (a syntax error is reported).

In the first place, the compiler will complain when you compare values of different types using the == operator and conversion cannot be performed.

In the previous example of Java code, if you want to make a comparison between x and y you could use equals:

int x = 10;
String y = "10";
System.out.println(y.equals(x)); // compile warning: Unlikely argument type for equals(): int seems to be unrelated to String

As a side note, notice the equals method cannot be called on primitive types.

Some useful readings are:

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • What about in Java 10 where you can now use `var`? – Nexevis Jun 20 '19 at 12:04
  • @Nexevis, Carlos Heuberger is right. It's the same with Java 10. Here: https://docs.oracle.com/javase/specs/jls/se10/html/jls-15.html#jls-15.21 – lealceldeiro Jun 20 '19 at 12:09
  • @CarlosHeuberger In JS: `var i = 10; var d = 10.0; console.log(i == d); /*true*/ console.log(i === d); /*true*/` – lealceldeiro Jun 20 '19 at 12:16
  • `var i = "10"; var d = 10.0; console.log(i == d);` is true in JS even, just tried it. – Nexevis Jun 20 '19 at 12:17
  • 1
    @lealceldeiro JavaScript doesn't have doubles or integers. Just "Numbers" which are essentially doubles. So `10` and `10.0` are both the same. – Ivar Jun 20 '19 at 12:26
  • @lealceldeiro `==` only checks for reference. If it's the same reference it can't be of another type – Felix Jun 20 '19 at 12:50
  • Amend to my last comment: The **compiler** (not the `==`) checks for reference type (thus the error at compile time) – lealceldeiro Jun 20 '19 at 14:22
  • @Ivar not it intirely true, as ```document.write(parseInt(10.0)``` and ```document.write(10.0)``` will write different things – JavaCakes Jun 20 '19 at 17:28
  • Okay so if I want to compare things of different types I need to do it manually or use try/catch – JavaCakes Jun 20 '19 at 17:34
  • 1
    @JavaCakes They write the same thing for me ([1](https://jsfiddle.net/q6vyr4ba/), [2](https://jsfiddle.net/3fa7btwy/)). – Ivar Jun 20 '19 at 17:40
  • The try-catch won't be needed. If you use `==` and those both things can not be compared, the compiler will tell you at compile time, otherwise it will compile and return `true` or `false` depending on their reference in memory. If you use `equals` the behavior is the same as `==` by default, but you can override it for any class you own and change how it behaves, being able this way, to return `true` or `false` also depending on the content of the object (its logical fields), and not only its reference in memory. Careful here on how you implement the `equals` method There are rules to do it – lealceldeiro Jun 20 '19 at 17:43
  • 2
    @Nexevis `var` in Java 10 is pure syntactic sugar to avoid writing the declaration type of the variable when it can be inferred from the created instance. The language is still strongly-typed. – M A Jun 24 '19 at 19:30
  • 1
    TL;DR: `===` in Java is `.equals()` – Cees Timmerman Apr 17 '23 at 08:07
6

I made a function which replicates the functionality of === of Javascript in Java

static boolean compareData(Object v1, Object v2)
{
    if(v1 != null && v2 != null)
        return (v1.getClass() == v2.getClass() && (v1.toString().equals(v2.toString())));
    else
    {
        return (v1 == null ? v2 == null : v1.equals(v2));
    }
}

I was able to pass values of any data type (except array) to this function as well as get true only if the data type and the values match else it returns false. Derived data types like List and HashMap also work.

Call to this function looks like this:

float s1 = 0.f;
float s2 = 0.1f;

System.out.println(compareData(s1, s2)); //Returns false

float s1 = 0.0f;
float s2 = 0.0f;

System.out.println(compareData(s1, s2)); //Returns true

float s1 = 0.1f;
String s2 = "0.1f";

System.out.println(compareData(s1, s2)); //Returns false 

String s1 = "sdf";
String s2 = null;

System.out.println(compareData(s1, s2)); //Returns false 

String s1 = null;
String s2 = null;

System.out.println(compareData(s1, s2)); //Returns true

and so on...

Update: I managed to compare arrays also, following is the code snippet, but, I haven't tested this code intensively but worked for every test case I performed.

if(s1 != null && s2 != null)
    if(s1.getClass().isArray() && s2.getClass().isArray())
        compareDatab = s1.getClass().equals(s2.getClass()) && (Arrays.toString(s1).equals(Arrays.toString(s2)));
    else
        compareDatab = compareData(s1, s2);
else
    compareDatab = compareData(s1, s2);

Usage of the above snippet (Following initializations should be done prior to above code snippet,smh :P):

//s1 and s2 can be anything including Arrays and non-Array...
int[] s1 = {1,2,3};
int[] s2 = {1,2,3};
//compareDatab gives true

int[] s1 = {1,2,4};
int[] s2 = {1,2,3};
//compareDatab gives false

float[] s1 = {1,2,3};
int[] s2 = {1,2,3};
//compareDatab gives false

Where compareData() is the same function as stated prior in this answer.

Hope this proves useful to you. :)

FutureJJ
  • 2,368
  • 1
  • 19
  • 30
  • 1
    This seems like it was a fun little project. +1 for going for it – JG7 Jun 24 '19 at 03:04
  • My advice is to use Objects.equals, Objects.deepEquals, Objects.hash, Objects.compare for stuff like that. The Objects class already contains a lot of your functionality you were coding by yourself. And it does null checks for you as well. One more benefit, it is tested and it does not happen that you insert a mistake. – Manuel Jul 01 '19 at 14:24
4

There is no concept of truthy and falsy in Java, thus there is no strict comparison operator.

Murat Karagöz
  • 35,401
  • 16
  • 78
  • 107
4

=== is useful in weak typed languages, such as Javascript, because it verifies that the objects being compared are of the same type and avoids implicit conversions.

=== has absolutely no use in a strongly typed language such as Java because you can't compare variables of different types without writing a specific method for doing this.

Istiaque Hossain
  • 2,157
  • 1
  • 17
  • 28
4

In Java you can compare primitive types like int, double, char, long, float by using '=='. In this case values are compared. For the comparison of objects this is not sufficient because '==' evaluates only to 'true' if the identities of the compared objects are the same - 'identity' is the memory address where the object is stored. This is due to the fact that all classes inherit implicitly all methods provided by the 'Object' class and where the 'equals()'-method contains only a basic implementation. Because of this any class whose objects are involved in comparisons, used in data structures or outside it's own package should contain a solid implementation of equals() and hashCode()-method to provide correct functionality.

Regard following implementation:

public class MyClass {

  private final int val;
  private final String name;

  public MyClass(int val, String name) {
     this.val = val;
     this.name = name;
  }

  public int getVal() { return val; }

  public String getName() { return name; }

  public boolean equals(Object o) {
     if(o == null) return false;
     if(this == o) return true;
     if(!this.getClass().getSimpleName().equals(o.getClass().getSimpleName()) return false;

     MyClass other = (MyClass) o;

     return this.getVal() == other.getVal() && this.getName().equals(other.getName());
  }

  public int hashCode() { ... }

}

Also check out official Java API for further information https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html .

3

I can't see any benefit of writing my own comparator for this. especially if there is already a native implementation for this.

java.util.Objects is your friend.

It contains a lot of little helper, like

Objects.compare(object1, object2, comparator);
Objects.equals(object1, object2);
Objects.deepEquals(object1, object2);
Objects.hash(object1, object2, object3, ...);

I use Objects.equals in overwriting in equals and Objects.hash in hashCode methods. It also does null checks for you and in the end the code looks very clean and readable.

In example:

...

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Customer)) {
        return false;
    }
    Customer that = (Customer) o;
    return Objects.equals(firstName, that.firstName)
            && Objects.equals(lastName, that.lastName)
            && Objects.equals(street, that.street)
            && Objects.equals(houseNumber, that.houseNumber)
            && Objects.equals(postalCode, that.postalCode)
            && Objects.equals(city, that.city)
            && Objects.equals(emailAddress, that.emailAddress);
}

@Override
public int hashCode() {
    return Objects.hash(firstName,
            lastName,
            street,
            houseNumber,
            postalCode,
            city,
            emailAddress);
}

...
Manuel
  • 1,928
  • 2
  • 16
  • 26
2

If two variables aren't of the same type you can't compare them, so in this case == will suffice. If they're not convertable it will throw a compiler error.

Tea_Lover_418
  • 308
  • 2
  • 10
2

There is no === operator for comparison. When you want to compare two references, you should check - 1. If they are pointing to same object.

if(firstreference==secondreference) 
  1. If condition 1 above did not meet then you should check for their type by instanceof operator :
if (secondreference instanctof classoffirstreference)
  1. If condition 2 above meets then you should check for property comparisons by equals operator like
firstreference.property1.equals(secondreference.property1)
//do this for all properties.
user
  • 867
  • 9
  • 21
0

If we compare two variables in JS we can use "==" and "===" both. "==" compare values and "===" compare Types also.

var x = 10;
var y = '10';
console.log(x == y)  // true
console.log(x === y) // false

and in Java this give you compile error because type is not same.

Manoj Kumar Rai
  • 103
  • 2
  • 10