English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Проблемы сравнения в Java - это очень базовая и часто запутанная тема. Сегодня я постараюсь详细归纳和整理一些容易出错的地方,希望能对大家的学习和面试有所帮助。
一、Разница между == и equals()
Сначала我们需要 понять разницу между == и equals(). == всегда сравнивает адреса. Для основных типов данных == сравнение на самом деле означает, что значения переменных равны, а для типов данных с ссылками это адреса. Здесь особенно важно отметить тип String, который легко сравнивать с ==, и это может привести к ошибкам. Метод equals() - это метод класса Object, и我们知道, что в Java все классы по умолчанию наследуют класс Object, поэтому все объекты класса имеют метод equals(). В методе equals() класса Object如下图所示:
Из исходного кода видно, что метод equals() в классе Object на самом деле использует ==, поэтому он сравнивает адреса. Поэтому, если мы хотим использовать метод equals() для других сравнений, нам нужно перегрузить этот метод.
二、Основные типы данных и их обертки
Мы знаем, что byte, short, int, long, boolean, char, double, float - это восемь основных типов данных, переменные которых хранятся в стека. А их соответствующие обертки (Byte, Short, Integer, Long, Boolean, Character, Double) определены в куче. Для основных типов данных сравнение относительно просто, то есть сравнение на равенство с помощью ==, а сравнение大小的 с помощью <, >, <=, >=. А для оберток это несколько по-другому.
Сначала посмотрим на результат выполнения следующего кода:
package dailytest; import org.junit.Test; /** * Обзор сравнения в Java * @author yrr */ public class JavaCompareTest { /** * Сравнение типов Integer */ @Test public void test01() { int n3 = 48; System.out.println("--------Использование нового объекта, когда значение находится в интервале [-127,128]---------"); Integer n7 = new Integer(48); Integer n8 = new Integer(48); System.out.println(n7 == n8); //false System.out.println(n7 == n3); //true System.out.println("--------Метод прямого назначения, когда значение находится в диапазоне [-128, 127]---------"); Integer n1 = 48; Integer n2 = 48; System.out.println(n3 == n1); //true System.out.println(n1 == n2); //true System.out.println(n1.equals(n2)); //true System.out.println(n1.equals(n3)); //true System.out.println(n1.intValue() == n2.intValue()); //true System.out.println("--------Прямой способ присвоения, когда значение не находится в интервале [-127,128]---------"); Integer n4 = 128; Integer n5 = 128; int n6 = 128; System.out.println(n4 == n5); //false System.out.println(n4 == n6); //true System.out.println(n4.equals(n5)); //true System.out.println(n4.equals(n6)); //true System.out.println(n4.intValue() == n5.intValue()); //true //При использовании метода Integer.intValue() необходимо проверить, не является ли传入ное значение null, чтобы избежать исключения NullPointException } /** * Сравнение типов Длинный на равенство */ @Test public void test02() { //Здесь需要注意, при определении с помощью long не нужно добавлять L или l, а при определении с помощью Длинный необходимо добавить, в противном случае будет выведено сообщение об ошибке //Добавление городов для区别 длинный n3 = 48L; System.out.println("--------Использование нового объекта, когда значение находится в интервале [-127,128]---------"); Длинный n7 = new Длинный(48); Длинный n8 = new Длинный(48); System.out.println(n7 == n8); //false System.out.println(n7 == n3); //true System.out.println("--------Прямой способ присвоения, когда значение находится в интервале [-127,128]---------"); Длинный n1 = 48L; Длинный n2 = 48L; System.out.println(n3 == n1); //true System.out.println(n1 == n2); //true System.out.println(n1.equals(n2)); //true System.out.println(n1.equals(n3)); //true System.out.println(n1.intValue() == n2.intValue()); //true System.out.println("--------Прямой способ присвоения, когда значение не находится в интервале [-127,128]---------"); Длинный n4 = 128L; Длинный n5 = 128L; длинный n6 = 128; System.out.println(n4 == n5); //false System.out.println(n4 == n6); //true System.out.println(n4.equals(n5)); //true System.out.println(n4.equals(n6)); //true System.out.println(n4.intValue() == n5.intValue()); //true //При использовании метода Long.intValue() необходимо проверить, не является ли он null, чтобы предотвратить возникновение NullPointException } }
Для результатов выполнения вышеуказанного, делается следующее объяснение:
Сначала, для объявления объекта Integer или Long с помощью метода new, потому что объекты new создаются в куче, поэтому, даже если значения одинаковые, для == сравниваются адреса, поэтому они возвращают false. Для упакованных классов базовых типов данных метод equals() был перезаписан, и он сравнивает значения, поэтому с помощью метода equals() можно judging по значениям. При сравнении Integer с int переменной会发现, что это также основано на сравнении значений, потому что при сравнении тип Integer делает автоматическое преобразование装箱а в тип int. Объяснение первых трех пунктов применяется ко всем упакованным типам. Для прямого способа присвоения, если у переменных Integer, значение которых 48, сравнение с помощью == возвращает true, а когда значение 128, то false. Это потому, что на самом деле для способа прямого присвоения, как Integer n1 = 48;, на самом деле вызывается метод Integer.value(). Давайте кратко посмотрим на исходный код метода Integer.value(), как показано на рисунке ниже:
Мы можем видеть, что здесь есть условный оператор if, когда вводимый i находится в диапазоне [-128, 127], он напрямую возвращает из массива IntegerCache. Поэтому, для значений в этом диапазоне, возвращаются адреса значений этого массива, поэтому сравнение с помощью == возвращает true. А те, которые не находятся в этом диапазоне, это созданные с помощью new объекты, поэтому они возвращают false. Этот вывод действует для типов Byte, Short, Integer, Long (интересующиеся могут увидеть исходный код их методов value()), потому что диапазон Byte составляет [-128, 127], поэтому для типа Byte использование == и equals() не имеет различий.
Для сравнения大小的, использование >, <, <=, >= не проблема, они будут выполнять автоматическое преобразование装箱а. Но мы обычно рекомендуем использовать следующие два способа для сравнения размеров:
Используйте метод xxxValue() для преобразования в базовый тип данных и сравнения. Используйте метод compareTo() для сравнения. В упакованных типах данных метод compareTo() был перезаписан. Просмотрите исходный код compareTo(), чтобы понять, что на самом деле он использует автоматическое преобразование装箱а в соответствующий базовый тип данных для сравнения.
Два. Сравнение объектов Java
После вышеуказанного введения сравнение объектов становится более легким. Принципы все те же.
1. Сравнение типов String
Следует отметить, что тип String не может быть напрямую использован с операторами >, <=, >=, <,否则 будет выведено компиляционное исключение.
package dailytest; import org.junit.Test; /** * Обзор сравнения в Java * @author yrr */ public class JavaCompareTest { @Test public void test03() { String s1 = new String("123"); String s2 = new String("123"); System.out.println(s1 == s2); //false System.out.println(s1.equals(s2)); String s3 = "234"; String s4 = "234"; System.out.println(s3 == s4); //true System.out.println(s3.equals(s4)); //true //System.out.println(s1 <= s3); //Оператор < не определен для типа аргумента(s) java.lang.String, java.lang.String System.out.println(s1.compareTo(s3) < 0); //true } }
2. Сравнение объектов класса
Результат сравнения объектов класса также аналогичен, но по сравнению с базовыми типами данных и типом String, он несколько сложнее.
Чтобы определить, равны ли два объекта по определенным правилам, необходимо переопределить метод equals() в классе, в котором выполняется проверка, пример кода см. ниже:
package dailytest; import org.junit.Test; /** * Обзор сравнения в Java * @author yrr */ public class JavaCompareTest { @Test public void test04() { Person p1 = new Person("yrr",18); Person p2 = new Person("yrr",18); System.out.println(p1 == p2); //false System.out.println(p2.equals(p1)); //true } } class Person{ private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public Integer getAge() { return age; } @Override public boolean equals(Object obj) { Person person = (Person) obj; return name.equals(person.getName()) && age.equals(person.getAge()); } }
Если нужно сравнить размер двух объектов (это также часто встречающийся вопрос на собеседовании), есть два способа:
Класс, сравниваемый, реализует интерфейс Comparable и переопределяет метод compareTo() Свою реализацию класса, реализующего интерфейс Comparator, или использование внутреннего класса, переопределяющего метод compare() Различия:前者 определен в классе, сравниваемом, а后者 вне класса. Благодаря этому различию, очевидны и их的优点 и недостатки:前者 прост, но требует изменений в классе, сравниваемом, а后者 не требует изменений в исходном коде и более гибок.
Первый способ, пример кода см. ниже:
package dailytest; import org.junit.Test; /** * Обзор сравнения в Java * @author yrr */ public class JavaCompareTest { @Test public void test5() { Person p1 = new Person("yrr",18); Person p2 = new Person("wx",19); System.out.println(p1.compareTo(p2) < 0); } } class Person implements Comparable<Person>{ private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public Integer getAge() { return age; } @Override public int compareTo(Person o) { return this.getAge() - o.getAge(); } }
Второй способ, пример кода см. ниже:
package comparator; import java.util.Arrays; import java.util.Comparator; public class MyComparator { public static void main(String[] args) { User[] users = new User[] { new User("u1001", 25), new User("u1002", 20), new User("u1003", 21) ; Arrays.sort(users, new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getAge() - o2.getAge(); } }); for (int i = 0; i < users.length; i++) { User user = users[i]; System.out.println(user.getId() + " " + user.getAge()); } } } class User { private String id; private int age; public User(String id, int age) { this.id = id; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
Вот все, что мы сегодня говорили о сравнении в Java, если у вас есть другие вопросы, вы можете обсудить их в评论区下方, спасибо за вашу поддержку.
Заявление: содержимое статьи взято из интернета, авторские права принадлежат соответствующему автору, материал был предоставлен пользователями Интернета, сайт не имеет права собственности, материал не был отредактирован вручную, также не несет ответственности за соответствующие правовые вопросы. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @), чтобы сообщить о этом, и предоставьте соответствующие доказательства. При обнаружении фактов, сайт немедленно удаляет涉嫌侵权的内容。