Еквивалент на “===” в 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 № === означава strictly equal в JavaScript. Не можете да го използвате за обекти, масиви, функции. Вижте тук за повече подробности.   -  person LiuXiMin    schedule 24.06.2019
comment
Ами всичко друго освен тези, тогава   -  person JavaCakes    schedule 24.06.2019
comment
Отговорът по-долу дава повече или по-малко обяснение, но бих казал, че не сравнявайте ябълки с портокали :) Всъщност най-близката аналогия, за която се сещам === в Java, всъщност е .equals(), ако сравнявате Strings или числа (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

Като странична бележка, забележете equals не може да се извика при примитивни типове.

Някои полезни четива са:

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

Успях да предам стойности от всякакъв тип данни (с изключение на масив) към тази функция, както и да получа true само ако типът данни и стойностите съвпадат, в противен случай тя връща false. Изведените типове данни като 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, като използвате '=='. В този случай стойностите се сравняват. За сравнението на обекти това не е достатъчно, защото '==' се оценява само като 'true', ако идентичностите на сравняваните обекти са еднакви - 'identity' е адресът на паметта, където се съхранява обектът. Това се дължи на факта, че всички класове наследяват имплицитно всички методи, предоставени от класа „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