Чи слід використовувати string.isEmpty () або “” .equals (string)?


171

У заголовку в основному все сказано. Я зазвичай тестую це поряд із string == null, тому я не дуже стурбований нульовим тестом. Який я повинен використовувати?

String s = /* whatever */;
...
if (s == null || "".equals(s))
{
    // handle some edge case here
}

або

if (s == null || s.isEmpty())
{
    // handle some edge case here
}

На цій замітці - чи isEmpty()навіть щось робить, крім return this.equals("");або return this.length() == 0;?


26
Майте на увазі, що isEmpty()це лише Java 6+.
ColinD

1
Ви можете створити допоміжний метод Util.String.hasValue (String s), який перевіряє наявність нуля, порожнечі та пробілу для обробки всіх справ.
Cloudanger

5
@ColinD Ймовірно, це не проблема - J2SE 5.0 деякий час тому завершив період закінчення терміну служби.
Том Хотін - тайклін

1
Інша річ, яку слід враховувати, це "" .equals () приймає Object як аргумент, тому ви не отримаєте помилку компілятора, якщо тип аргументу зміниться з String на щось інше, на краще чи гірше.
Пол Джексон

Відповіді:


251

Основна перевага "".equals(s)полягає в тому, що вам не потрібна перевірка нуля ( equalsперевірятиме її аргумент і повертається, falseякщо вона є нульовою), яка, здається, не хвилює вас. Якщо ви не турбуєтесь про sте, що це недійсне (або іншим чином перевіряєте це), я б точно скористався s.isEmpty(); він показує саме те, що ви перевіряєте, вас дбає, чи sпорожній він чи ні, чи не дорівнює він порожній рядку


29
Дякую за пояснення. Тепер я знаю, чому надавати перевагу "" .equals (str) над str.equals ("")! Мені завжди було цікаво, чому інші так часто використовують це, але не враховували нульових значень. Чудово :-)
Пітер Віпперман

10
ІМХО, нульова перевірка все ще потрібна у наведених вище прикладах, оскільки ми припускаємо, що умова має бути істинною для нульового значення. s == null || "" .equals (s)
mkorpela

5
@ Master.Aurora ні, якщо getValue()повернеться null, ви отримаєте NullPointerException, коли toString()його викликали
ataulm

12
@RenniePet Це не так, як якась магія. Якщо snull, ви не можете викликати методи на ньому - це null. ""ніколи не буде нульовим, тому ви можете безпечно викликати методи на ньому, і equals()можете обробити той випадок, коли його аргумент є нульовим
Michael Mrozek

5
Примітка про продуктивність: isEmpty()перевіряє внутрішню довжину приватного масиву, тоді як equals(Object anObject)робить набагато більше (наприклад, перевірка instanceof). Парфумерно, isEmpty()як правило, швидше.
Turing85

82

String.equals("")насправді трохи повільніше, ніж просто isEmpty()дзвінок. Струни зберігають змінну ініціалізації в конструкторі, оскільки рядки незмінні.

isEmpty() порівнює змінну підрахунку до 0, тоді як дорівнює рівню перевірятиме тип, довжину рядка, а потім повторює рядок для порівняння, якщо розміри відповідають.

Отже, щоб відповісти на ваше запитання, isEmpty()насправді буде робити набагато менше! і це добре.


3
Я думаю, що в цьому випадку різниця не застосовується; ніколи не буде ітерації над рядками для порівняння, тому що розміри не збігаються (якщо рядок насправді порожній, і тоді немає символів для повторення)
Michael Mrozek

2
Правда, але при рівних рівнях ви спочатку проводите контрольну перевірку, щоб побачити, чи є вони тим самим об'єктом, потім екземпляр, потім екземпляр, а потім присвоєння строці, перевірка довжини, а потім нарешті ітерація. Якщо обидва рядки були порожніми, то це була б просто проста перевірка довідки.
Девід Янг

вихідний код до класу String доступний java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
Девід Янг

1
@David мертве посилання; ось прямий ефір docjar.com/html/api/java/lang/String.java.html#1011
Метт Бал

17

Одне, що ви, можливо, захочете розглянути, окрім інших згаданих питань, це те, що isEmpty()було введено в 1.6, тож якщо ви ним скористаєтеся, ви не зможете запустити код на Java 1.5 або нижче.


4
Це напевно не хвилює мене.
Метт Бал

1
Також ця відповідь зараз 6 років тому. Я сподіваюся, що більше ніхто не повинен використовувати щось давнє, як Java 1.5.
Міша Наследов

1
Насправді багато речей, які можуть зламатися при модернізації версії java. Це менш важливо для бек-енд-додатка, який працює на великому сервері, але це важливо для клієнтських додатків. На графічні бібліотеки та стратегії збору сміття часто впливають великі та незначні оновлення Java. Крім того, клієнтське програмне забезпечення може працювати в різних операційних системах, а іноді і з обмеженою пам’яттю, а значить, у вас часто не вистачить бюджету / ресурсів для тестування всього. - Так, у мене є клієнти, які все ще дотримуються Java 5 у 2017 році.
bvdb


2

Це насправді не має значення. "".equals(str)на мою думку, більш зрозуміло.

isEmpty()повертає count == 0;


47
Я б сказав, str.isEmpty()це набагато зрозуміліше, ніж "".equals(str). Він читається як те, що ви перевіряєте. Однак, мабуть, питання думки.
ColinD

7
Я думаю, що деякі люди вважають за краще робити "" .equals (str), щоб уникнути NPE. Мені особисто це не подобається, тому що я швидше спершу перевіряю, чи рядок не є нульовим спочатку.
CoolBeans

2

Я написав тестер-клас, який може перевірити продуктивність:

public class Tester
{
    public static void main(String[] args)
    {
        String text = "";

        int loopCount = 10000000;
        long startTime, endTime, duration1, duration2;

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.equals("");
        }
        endTime = System.nanoTime();
        duration1 = endTime - startTime;
        System.out.println(".equals(\"\") duration " +": \t" + duration1);

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.isEmpty();
        }
        endTime = System.nanoTime();
        duration2 = endTime - startTime;
        System.out.println(".isEmpty() duration "+": \t\t" + duration2);

        System.out.println("isEmpty() to equals(\"\") ratio: " + ((float)duration2 / (float)duration1));
    }
}

Я виявив, що використання .isEmpty () займає приблизно половину часу .equals ("").


Це не є дійсним мікро-орієнтиром. Я настійно рекомендую використовувати суппорт або подібний спеціально створений інструмент бенчмаркінгу. stackoverflow.com/q/504103/139010
Метт Бал

Дякую за пораду! Коли я отримаю трохи вільного часу, я буду експериментувати з деякими мікро-бенчмаркінгами та оновити свою відповідь.
conapart3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.