Java преобразование переменной int в String путем добавления пустой строки? - PullRequest
0 голосов
/ 25 января 2020

Второй аргумент вызова addFormDataPart должен быть строкой.

 int privacyLevel = 0;
 builder.addFormDataPart("privacy",privacyLevel);

Однако, поскольку privacyLevel является целым числом, его необходимо преобразовать в строку.

enter image description here
В учебнике он сделал преобразование путем добавления пустой строки в конце privacyLevel:

builder.addFormDataPart("privacy",privacyLevel+"");

Я обнаружил, что это необычный способ преобразования int в строку. И все исследования, которые я провел, указывали мне на традиционные методы обращения.
Так есть ли у кого-нибудь объяснение этому? И это даже "хорошая практика"?

1 Ответ

1 голос
/ 25 января 2020

Вы также можете использовать подходящий инструмент: Integer.toString(int): это может быть проще для чтения, поскольку оно ясно показывает ваше намерение получить String из вашего int.

int privacyLevel = 0;
builder.addFormDataPart("privacy", Integer.toString(privacyLevel));

Когда вы используете:

builder.addFormDataPart("privacy", "" + privacyLevel);

Вы создаете новую строку из "" и Integer.toString(privacyLevel), но возможна некоторая оптимизация во время компиляции или во время выполнения:

  • Компилятор может обнаружить "" и напрямую использовать Integer.toString(privacyLevel).
  • Компилятор может заменить операцию + методом String::concat. Указанный метод может вернуть другой String, если сам по себе пуст, или вернуть себя, когда other String пуст (в openjdk 8u232 метод фактически проверяет длину other и всегда выполняйте конкатенацию).

Теперь, чтобы увидеть, что делает компилятор, вот простой код, который ничего необычного не делает:

class Foobar {
  public static void main(String[] args) {
    int n = 1;
    String s = n + "";
  }
}

Если вы вызываете javap -p Foobar.class, вы можете увидеть, что сделал компилятор (с Java 11.0.6, Java 8 используйте StringBuilder):

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=1
         0: iconst_1
         1: istore_1
         2: iload_1
         3: invokedynamic #2,  0              // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
         8: astore_2
         9: return
      LineNumberTable:
        line 8: 0
        line 9: 2
        line 10: 9

Используя Integer.toString, измените только invokedynamic на invokestatic:

3: invokestatic  #2                  // Method java/lang/Integer.toString:(I)Ljava/lang/String

Компилятор не пытается быть интеллектуальным в этом случае и не оптимизирует "" + int.

Если вы читаете Javado c из java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup, String, MethodType, String, Object...), он ссылается на JLS 15.18.1 и JLS 5.1.11 .

JLS 15.18.1 объясняет операцию конкатенации из String + Не строка :

Если только одно выражение операнда имеет тип String, то преобразование строки (§5.1.11) выполняется для другого операнд для создания строки во время выполнения.

В JLS 5.1.11 объясняется, как преобразовать int в String:

Значение x примитивного типа T сначала преобразуется в ссылочное значение, как если бы оно передавалось в качестве аргумента соответствующему выражению создания экземпляра класса (§15.9):

If T is byte, short, or int, then use new Integer(x).

Чтобы ответить на ваш вопрос:

Я обнаружил, что это необычный способ преобразования int в строку. И все исследования, которые я провел, указывали мне на традиционные методы обращения. Так у кого-нибудь есть объяснение этому? И это даже "хорошая практика"?

Что необычно в вашем случае, если тот факт, что String идет после числа, а не до (как в "privacyLevel: " + privacyLevel), но это не странно, учитывая JLS 15.18.1 .

Я не могу сказать, что это хорошая практика, хотя она и относительна, но я бы сказал, что это наследие практика, рожденная для того факта, что Integer.toString не является такой старый (я не могу вспомнить, был ли он добавлен в Java 5 или 6) и что проще было сделать n + "" или "" + n.

Я бы лично поддержал Integer.toString, потому что Я нахожу n + "" довольно некрасивым. Это также может быть лучше с точки зрения производительности из-за сложности преобразования, выполненного в противном случае. К счастью для вас или моего ответа, кто-то сделал JMH-тест .

И последнее, но не менее важное: если вы будете придерживаться конкатенации, результат будет зависеть от версии компилятора, который будет выполнять преобразование:

  • Вы используете Android Studio, и то, что применимо к vanilla Java, может быть не полностью применимо здесь.
  • Java 8 используйте StringBuilder для генерации int 'String.
  • Java 11 используют invokedynamic и много чего сложного (для меня), чтобы объяснить, но я предполагаю, что он делает свою работу и работает так же хорошо, если лучше, чем StringBuilder.
  • Integer.toString, кажется, оптимизирован в новой JVM горячей точки (он аннотирован @HotSpotIntrinsicCandidate в Java 13).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...