Эквивалент «===» в Java

Как при сравнении двух значений в Java проверить, эквивалентны ли и тип, и значение?

Я знаю, что для этого можно использовать === JavaScript, поэтому я попробовал это на Java, но это не сработало.

Я знаю, что это простой вопрос, но я попытался найти его, но не смог узнать, что это было.


person JavaCakes    schedule 20.06.2019    source источник
comment
a.equals(b) правильно написанным equals методом.   -  person luk2302    schedule 20.06.2019
comment
В JavaScript === нельзя использовать для проверки эквивалентности и типа, и значения. var obj_a = {1: 2}; var obj_b = {1: 2}; console.log(obj_a === obj_b); // result is false   -  person LiuXiMin    schedule 24.06.2019
comment
@LiuXiMin Я думаю, он не работает только с объектами, но он работает со всем остальным   -  person JavaCakes    schedule 24.06.2019
comment
@JavaCakes No. === означает strictly equal в JavaScript. Нельзя использовать для объектов, массивов, функций. Дополнительные сведения см. здесь.   -  person LiuXiMin    schedule 24.06.2019
comment
Ну все, кроме тех, тогда   -  person JavaCakes    schedule 24.06.2019
comment
Приведенный ниже ответ более или менее дает объяснение, но я бы сказал, не сравнивайте яблоки с апельсинами :) На самом деле, самая близкая аналогия, которую я могу придумать для === в Java, на самом деле .equals(), если вы сравниваете Strings или Numbers (Integer до Integer или от Double до Double), но для примитивов и других ссылочных типов это ==, но при сравнении Integer с Double (разные типы в штучной упаковке) эквивалента нет. В итоге постарайтесь понять, как каждый оператор работает на конкретном языке, который вы используете. Проведение аналогий между двумя разными языками скорее запутает, чем поможет.   -  person M A    schedule 24.06.2019


Ответы (9)


TL; DR

В Java нет такого оператора сравнения: ===, но == или equals

Более подробное объяснение

В слабо типизированных языках, таких как JavaScript, вы можете использовать оператор строгого сравнения (===), потому что язык позволяет сравнивать переменные, которые имеют разные типы.

Например, в JavaScript вы не получите ошибку компиляции, если сделаете следующее:

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

И это полезно, когда вы хотите сравнить переменные, которые могут содержать «равные» значения, но могут быть разных типов.

Например

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

В строго типизированных языках, таких как Java, вам не нужно использовать строгий оператор сравнения, потому что язык уже «обрабатывает» сравнение типов.

Например:

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

Таким образом, в Java нет необходимости проверять строгость с помощью === (сообщается о синтаксической ошибке).

Во-первых, компилятор будет жаловаться, когда вы сравниваете значения разных типов с помощью оператора == и преобразование невозможно.

В предыдущем примере кода Java, если вы хотите сравнить x и y, вы можете использовать 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

В качестве побочного примечания обратите внимание на _ 14_ нельзя вызывать для примитивных типов.

Некоторые полезные чтения:

person lealceldeiro    schedule 20.06.2019
comment
А как насчет Java 10, где теперь можно использовать var? - person Nexevis; 20.06.2019
comment
@Nexevis, Карлос Хойбергер прав. То же самое и с Java 10. Здесь: docs.oracle.com/javase/specs/jls/se10/html/ - person lealceldeiro; 20.06.2019
comment
@CarlosHeuberger В JS: var i = 10; var d = 10.0; console.log(i == d); /*true*/ console.log(i === d); /*true*/ - person lealceldeiro; 20.06.2019
comment
var i = "10"; var d = 10.0; console.log(i == d); правда даже в JS, только пробовал. - person Nexevis; 20.06.2019
comment
@lealceldeiro JavaScript не имеет двойных или целых чисел. Просто числа, которые по сути являются двойными. Итак, 10 и 10.0 одинаковы. - person Ivar; 20.06.2019
comment
@lealceldeiro == проверяет только ссылки. Если это та же ссылка, она не может быть другого типа - person Felix; 20.06.2019
comment
Исправить мой последний комментарий: компилятор (не ==) проверяет ссылочный тип (таким образом, ошибка во время компиляции) - person lealceldeiro; 20.06.2019
comment
@Ivar не совсем верно, так как document.write(parseInt(10.0) и document.write(10.0) будут писать разные вещи - person JavaCakes; 20.06.2019
comment
Хорошо, поэтому, если я хочу сравнить вещи разных типов, мне нужно сделать это вручную или использовать try / catch - person JavaCakes; 20.06.2019
comment
@JavaCakes Мне пишут то же самое (1, 2). - person Ivar; 20.06.2019
comment
Пробный улов не понадобится. Если вы используете == и эти две вещи нельзя сравнивать, компилятор сообщит вам во время компиляции, иначе он скомпилирует и вернет true или false в зависимости от их ссылки в памяти. Если вы используете equals, поведение по умолчанию такое же, как ==, но вы можете переопределить его для любого принадлежащего вам класса и изменить его поведение, имея возможность таким образом возвращать true или false, также в зависимости от содержимого объекта (его логические поля), а не только его ссылка в памяти. Будьте внимательны при реализации метода equals. Для этого существуют правила. - person lealceldeiro; 20.06.2019
comment
@Nexevis var в Java 10 - это чистый синтаксический сахар, позволяющий избежать записи типа объявления переменной, когда он может быть выведен из созданного экземпляра. Язык по-прежнему строго типизирован. - person M A; 24.06.2019

Я сделал функцию, которая r воплощает функциональность === Javascript в 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));
    }
}

Мне удалось передать значения любого типа данных (кроме массива) в эту функцию, а также получить истину, только если тип данных и значения совпадают, иначе она вернет ложь. Производные типы данных, такие как List и HashMap, также работают.

Вызов этой функции выглядит так:

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

и так далее...

Обновление: Мне также удалось сравнить массивы, ниже показан фрагмент кода, но я не тестировал этот код интенсивно, но работал с каждым выполненным мной тестовым примером.

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);

Использование приведенного выше фрагмента (следующие инициализации должны быть выполнены до фрагмента кода выше, 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

Где compareData () - та же функция, что указана ранее в этом ответе.

Надеюсь, это окажется для вас полезным. :)

person FutureJJ    schedule 23.06.2019
comment
Похоже, это был забавный маленький проект. +1 за то, что пошел на это - person JG7; 24.06.2019
comment
Мой совет - использовать Objects.equals, Objects.deepEquals, Objects.hash, Objects.compare для подобных вещей. Класс Objects уже содержит многие функции, которые вы кодировали самостоятельно. И он также выполняет нулевые проверки для вас. Еще одно преимущество, это проверено и не бывает, чтобы вы вставляли ошибку. - person Manuel; 01.07.2019

В Java нет концепции истинности и ложности, поэтому нет оператора строгого сравнения.

person Murat Karagöz    schedule 20.06.2019
comment
Так что !(false == 0) правда - person JavaCakes; 20.06.2019

=== полезен в языках со слабой типизацией, таких как Javascript, поскольку он проверяет, что сравниваемые объекты имеют один и тот же тип, и позволяет избежать неявных преобразований.

=== абсолютно бесполезен в строго типизированном языке, таком как Java, потому что вы не можете сравнивать переменные разных типов, не написав для этого специальный метод.

person Istiaque Hossain    schedule 20.06.2019

В Java вы можете сравнивать примитивные типы, такие как int, double, char, long, float, используя '=='. В этом случае сравниваются значения. Для сравнения объектов этого недостаточно, потому что «==» оценивается только как «истина», если идентичности сравниваемых объектов одинаковы - «идентичность» - это адрес памяти, где хранится объект. Это связано с тем, что все классы неявно наследуют все методы, предоставляемые классом Object, а метод equals () содержит только базовую реализацию. По этой причине любой класс, чьи объекты участвуют в сравнении, используются в структурах данных или вне его собственного пакета, должен содержать надежную реализацию equals () и hashCode () - метода для обеспечения правильной функциональности.

Что касается следующей реализации:

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

}

Также ознакомьтесь с официальным Java API для получения дополнительной информации https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html.

person eulersexception    schedule 20.06.2019

Я не вижу никакой пользы от написания собственного компаратора для этого. особенно если для этого уже есть нативная реализация.

java.util. Objects - ваш друг.

Он содержит много маленьких помощников, таких как

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

Я использую Objects.equals для перезаписи в equals и Objects.hash в методах hashCode. Он также выполняет нулевые проверки за вас, и в итоге код выглядит очень чистым и читаемым.

Например:

...

@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);
}

...
person Manuel    schedule 01.07.2019

Если две переменные не одного типа, вы не можете их сравнивать, поэтому в этом случае будет достаточно ==. Если они не могут быть преобразованы, компилятор выдаст ошибку.

person Tea_Lover_418    schedule 20.06.2019

Для сравнения нет оператора ===. Если вы хотите сравнить две ссылки, вы должны проверить - 1. Если они указывают на один и тот же объект.

if(firstreference==secondreference) 
  1. Если условие 1 выше не выполнено, вам следует проверить их тип с помощью оператора instanceof:
if (secondreference instanctof classoffirstreference)
  1. Если выполняется условие 2, указанное выше, вы должны проверить сравнение свойств с помощью оператора равенства, например
firstreference.property1.equals(secondreference.property1)
//do this for all properties.
person Rajni Kewlani    schedule 20.06.2019

Если мы сравним две переменные в JS, мы можем использовать обе «==» и «===». «==» сравнивает значения и «===» также сравнивает типы.

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

а в Java это дает ошибку компиляции, потому что тип не тот.

person Manoj Kumar Rai    schedule 24.06.2019