CONSTANT.equals (VARIABLE) быстрее, чем VARIABLE.equals (CONSTANT)?

У меня был интересный разговор с одним из моих товарищей по команде.

ЯвляетсяCONSTANT.equals(VARIABLE) быстрее, чемVARIABLE.equals(CONSTANT) на Яве?

Я подозреваю, что это ложное утверждение. Но я пытаюсь понять, что за этим стоит качественная аргументация?

Я знаю, что в обоих случаях производительность не будет отличаться ни от одного существенного состояния. Но это была рекомендация по ЛУЧШЕЙ ПРАКТИКЕ, которая делает меня неудобным. Вот почему я ищу веские аргументы, которые я хочу представить в этом деле.

Пожалуйста помог

 Jigar Joshi06 июн. 2012 г., 10:57
Разницы в производительности нет, но есть разница, пожалуйста, проверьте Stackoverflow.com / вопросы / 5712100 / интервью-ява-равно
 Joachim Sauer06 июн. 2012 г., 10:57
@ JigarJoshi: этот вопрос конкретно о скорости, а о связанном - нет.
 Jigar Joshi06 июн. 2012 г., 10:56
Возможный дубликатInterview: Java Equals
 Joachim Sauer06 июн. 2012 г., 10:56
У меня есть более важный вопрос: есть ли ситуации, когда (гипотетическая) разница будет иметь значение?
 Jigar Joshi06 июн. 2012 г., 10:58
@ Йоахим Согласен, я должен был пометить его как связанный, не могу вернуть его сейчас

Ответы на вопрос(7)

код в java.langString поддерживает мой ответ.

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }
 tibo06 июн. 2012 г., 11:33
Если это не строка, это означает, что ее метод равно отличается и поэтому может быть не симметричным
 tibo06 июн. 2012 г., 11:07
Это симметрично, только если anObject является строкой ...
 Ashish Agarwal06 июн. 2012 г., 11:08
@ tibo Не могли бы вы уточнить ваше последнее утверждение.
 assylias06 июн. 2012 г., 11:01
Это выглядит довольно симметрично для меня ...

private static String EXAMPLE = "Example";
private String obj = null;

Случай 1

if(obj.equals(EXAMPLE) {
}

Это исключение броска нулевого указателя ..

case 2:

if(EXAMPLE.equals(obj)) {
}

Это не сгенерирует исключение нулевого указателя ..

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

Одним из преимуществ Constant.equals (переменная) является то, что вы не можете иметь исключение NullPointerException для .equals

 Ashish Agarwal06 июн. 2012 г., 11:18
NullPointerException очень хорошо известна, поэтому я в основном фокусируюсь на производительности.
 Joachim Sauer06 июн. 2012 г., 11:23
@ Frank: 1. Java не является акрином, поэтому это «Java», 2. Даже если производительность невелика, соображения производительности могут все еще быть интересными (разница между «плохими» и «ужасными») и 3. Java довольно хороша в наши дни с производительностью, вы распространяете FUD.
 Franz Ebner06 июн. 2012 г., 11:41
@ Joachim Sauer 1. Я пишу на JAVA так, как хочу, есть ли у вас 76k или нет, 2. Говоря о производительности на JVM, работающей с (предположительно) DOS-NT-вложением (DOS & NT - аббревиатуры), фундаментально плотная, 3 Это сайт QA, и моя последняя запись была ответом, отличным от вашего.
 Franz Ebner06 июн. 2012 г., 11:21
Производительность - это не то, чем JAVA известен вообщ

Если мы сравнимлюч @CONSTANT (левая часть метода equals) с любогоObject (правая часть метода equals) тогда компилятор может проверить сравнение и дать ожидаемый результат, но если мы сделаем наоборотObject ((Левая часть метода equals)) в сравнении с Постоянный ключ ((правая часть метода equals)) тогда ваша программа может черезИСКЛЮЧЕНИЕ НУЛЕВОГО УКАЗАТЕЛ.

public static void main(String[] args) {
        String CONSTANT_KEY = "JAVA";
        String string = null;

        // CASE 1
        if (CONSTANT_KEY.equals(string)) {
            System.out.println("I am in if block");
        }

        // CASE 2   
        if (string.equals(string)) {
            System.out.println("I am in if block");
        }
    }

В приведенном выше примере кода 1 всегда безопасно сравнивать объекты, чтобы исключить исключение NULL POINTER вместо случая 2.

например

"Hello".equals(a); // will never throw a NPE
a.equals("Hello"); // can throw an NPE.

Ты можешь предпочесть, чтобы он взорвался, когда аnull но обычно нет.

Решение Вопроса

public class EqualsTest {
    public static String CONST = "const";
    public void constEqVar(String var) {
        CONST.equals(var);
    }
    public void varEqConst(String var) {
        var.equals(CONST);
    }
}

Затем я скомпилировал его, используя javac:javac EqualsTest.java и разобрал его используяjavap: javap -c EqualsTest.

Вот соответствующий фрагмент вывода javap:

public void constEqVar(java.lang.String);
  Code:
   0:   getstatic       #2; //Field CONST:Ljava/lang/String;
   3:   aload_1
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

public void varEqConst(java.lang.String);
  Code:
   0:   aload_1
   1:   getstatic       #2; //Field CONST:Ljava/lang/String;
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

Как вы можете видеть, единственное различие между этими двумя методами заключается в порядке операций: getstatic и затем aload_1 в первом случае и aload_1 + getstatic во втором случае.

Довольно очевидно, что время выполнения не должно зависеть от этого порядка.

Единственная причина, чтобы предпочестьconst.equals(var) скорее, чемvar.equals(const) стоит избегатьNullPointerException.

Сделайте простой тест со строками:

final String constHello = "Hello";
final int times = 1000000000;

long constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    constHello.equals("Hello");
}

long constTimeStop = System.nanoTime();

System.out.println("constHello.equals(\"Hello\"); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");


constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    "Hello".equals(constHello);
}

constTimeStop = System.nanoTime();

System.out.println("\"Hello\".equals(constHello); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");

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

 Joachim Sauer06 июн. 2012 г., 11:23
Обратите внимание, что вы всегда будете сталкиваться с быстрым путем при сравнении, поскольку оба объекта на самом деле являются одними и теми же объектами. Кроме того, вы тестируете код, который не работает, потому что он не учитывает время прогрева.
 Mats Adborn06 июн. 2012 г., 11:42
@ Joachim Sauer: Вы правы. Имело неполное понимание того, как сделать эти тесты. Спасибо за разъяснение

Ваш ответ на вопрос