Манипулирование строкой в ​​пуле с постоянными значениями по сравнению с Манипулированием строк в пуле с неконстантными значениями - Perfomance - PullRequest
0 голосов
/ 24 января 2019

Я хотел изменить код, который был похож на

if("T".equalsIgnoreCase(bo.getSubjectType()))  //method-1

до

if(String.valueOf('T').equalsIgnoreCase(bo.getSubjectType()))  //method-2

По этой причине я написал пример кода

String s1 = "T";
String s2 = "T";
char c1 = 'T';
char c2 = 'T';
System.out.println(String.valueOf(c1) == String.valueOf(c2));   //  false
System.out.println(s1 == s2);   //  true

Что говорит о том, что String.valueOf(arg) создает строковый литерал и помещает его в constant pool. Поэтому мой вопрос заключается в том, будет ли какой-либо контраст в производительности, когда мы попытаемся манипулировать строкой в ​​non-constant пуле и в constant pool - в основном, какой из них лучше подходит method-1 или метод-2

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Метод 2 трудно читаемый и вообще не имеет улучшений.

String, созданный с помощью оператора оператора new, он всегда создает новый объект в динамической памяти.String, созданный с использованием String literal, может вернуть существующий объект из String pool, если он уже существует.

Он не вернет String из пула и создаст String с использованием new оператор (источник Oracle JDK 10):

 /**
 * Returns the string representation of the {@code char}
 * argument.
 *
 * @param   c   a {@code char}.
 * @return  a string of length {@code 1} containing
 *          as its single character the argument {@code c}.
 */
public static String valueOf(char c) {
    if (COMPACT_STRINGS && StringLatin1.canEncode(c)) {
        return new String(StringLatin1.toBytes(c), LATIN1);
    }
    return new String(StringUTF16.toBytes(c), UTF16);
}

Если вы хотите определить String константу, которая всегда будет загружаться из пула, просто создайте:

public static final String T = "T";

Из JLS о строковых литералах и пулах:

class Test {
   public static void main(String[] args) {
   String hello = "Hello", lo = "lo";
   System.out.print((hello == "Hello") + " ");
   System.out.print((Other.hello == hello) + " ");
   System.out.print((other.Other.hello == hello) + " ");
   System.out.print((hello == ("Hel"+"lo")) + " ");
   System.out.print((hello == ("Hel"+lo)) + " ");
   System.out.println(hello == ("Hel"+lo).intern());
 }
}
class Other { static String hello = "Hello"; }

и блок компиляции:

package other; 
public class Other { 
    public static String hello = "Hello"; 
}

производит вывод:

true true true true false true

Этот пример иллюстрирует шесть пунктов:

• Литеральные строки в одном и том же классе (§ 8 (классы)) в одном пакете (§ 7 (пакеты)) представляют ссылки на один и тот же объект String.(§4.3.1).

• Литеральные строки в разных классах в одном и том же пакете представляют ссылки на один и тот же объект String.

• Литеральные строки в разных классах в разных пакетах также представляют ссылки на один и тот же объект String.

• Строки, вычисленные с помощью константных выражений (§15.28), вычисляются во время компиляции, а затем обрабатываются так, как если бы они были литералами.

• Строки, вычисленные путем конкатенации во время выполнения, создаются заново и поэтому различаются.

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

0 голосов
/ 24 января 2019
if(String.valueOf('T').equalsIgnoreCase(bo.getSubjectType()))

Нет никакого преимущества в том, чтобы писать это так.

String.valueOf('T') всегда будет возвращать новую строку, равную "T", потому что результат String.valueOf(char) (или любой valueOf перегрузка, в этом отношении) не кешируется.Нет смысла продолжать создавать одну и ту же строку снова и снова.

Плюс, она более многословна.

Просто придерживайтесь метода 1.

...