Подтвердить что ты не робот

Где `+` реализовано для строк в исходном коде Java?

String - частный случай в Java. Это класс, который я могу изучить в исходный код, но он также имеет свой собственный инфиксный оператор +, который, кажется, является синтаксическим сахаром для StringBuilder.

Например,

"Hello " + yourName;

может стать

new StringBuilder().append("Hello ").append(yourName).toString();

В Java нет пользовательских операторов, поэтому где + указано для String?

Можно ли использовать тот же механизм для создания дополнительных операторов, например, для векторов?

4b9b3361

Ответ 1

+ реализован в java-компиляторах. Компилятор заменяет String + String на константы времени компиляции или код StringBuilder. Обратите внимание, что это также относится к примитивам. i.e, int i=1+2 может быть непосредственно заменен на int i=3 во время самой компиляции.

Ответ 2

Вы можете проверить со спецификацией. У компилятора есть его реализация, а не исходный код Java.

Java Language Specification- 15.18.1. String Concatenation Operator +

Реализация может решить выполнить преобразование и конкатенацию за один шаг, чтобы избежать создания и затем отбрасывания промежуточного объекта String. Чтобы увеличить производительность повторной конкатенации строк, компилятор Java может использовать класс StringBuffer или подобный метод для уменьшения количества промежуточных объектов String, созданных при оценке выражения.

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

Ответ 3

Компиляторы Java имеют реализацию для+. Javadocs говорит:

Язык Java обеспечивает специальную поддержку для строки оператор конкатенации (+), а для преобразования других объектов в строки. Конкатенация строк осуществляется через StringBuilder (или StringBuffer) и его метод добавления. String преобразования реализуются с помощью метода toString, определенного Объект и унаследован всеми классами Java. Для дополнительных информация о конкатенации и конвертации строк, см. Гослинг, Радость, и Steele, Спецификация языка Java.

Вы можете попробовать это:

public static void main(String[] args) {
    String s1 = "s1";
    String s2 = "s2";
    String s3 = s1 + s2;
    String s4 = new StringBuilder(s1).append(s2).toString();
}

Приведенный выше код генерирует один и тот же байт-код для + и при использовании StringBuilder:

L0
LINENUMBER 23 L0
LDC "s1"
ASTORE 1

L1
LINENUMBER 24 L1
LDC "s2"
ASTORE 2

// s3 = s1 + s2

L2
LINENUMBER 25 L2

NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

ASTORE 3

// s4 = new StringBuilder(s1).append(s2).toString()

L3
LINENUMBER 26 L3

NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

ASTORE 4
L4
LINENUMBER 27 L4
RETURN

Ответ 4

В настоящее время большинство компиляторов Java, использующих цепочку StringBuilder, не указали, что это должно быть всегда таким образом. В частности, есть предложение , чтобы радикально изменить это в Java-9, заменив одним вызовом invokedynamic и представив новый метафайл, который будет генерировать подходящий MethodHandle во время выполнения для выполнения конкатенация.

Ответ 5

Что касается языка, нет, он не растяжимый. Это конкретное поведение, ни один другой класс не расширяет оператор +.

Что касается этого, выполните поиск string_add (а не настоящий JVM op) в следующих файлах:


Что касается того, почему Java должен был быть простым или, по крайней мере, проще, чем С++, и базовая вещь, такая как манипуляция строк, была обязательной. Однако перегрузка оператора могла бы усложнить ситуацию.