Почему в Java вы можете добавлять строки с оператором +, когда String является классом? В коде String.java
я не нашел никакой реализации для этого оператора. Означает ли это понятие объектная ориентация?
Как класс String переопределяет оператор +?
Ответ 1
Посмотрите на следующие простые выражения в Java
int x=15;
String temp="x = "+x;
Компилятор преобразует "x = "+x;
в StringBuilder
внутренне и использует .append(int)
для "добавления" целых чисел в строку.
Любой тип может быть преобразован в тип String путем преобразования строки.
Значение х примитивного типа T сначала преобразуется в опорное значение как если бы он передал его как аргумент соответствующему экземпляру класса (§15.9):
- Если T булево, то используйте новый Boolean (x).
- Если T char, используйте новый символ (x).
- Если T является байтом, коротким или int, то используйте новый Integer (x).
- Если T длинно, используйте новый Long (x).
- Если T является float, используйте новый Float (x).
- Если T двойное, используйте новый Double (x).
Это ссылочное значение затем преобразуется в тип String по строке преобразование.
Теперь нужно учитывать только опорные значения:
- Если ссылка имеет значение null, она преобразуется в строку "null" (четыре символа ASCII n, u, l, l).
- В противном случае преобразование выполняется как бы путем вызова метода toString ссылочного объекта без аргументов; но если результат вызова метода toString равен нулю, тогда Вместо этого используется строка "null".
Метод toString определяется примитивным классом Object (§4.3.2). Многие классы переопределяют его, в частности Boolean, Character, Integer, Long, Float, Double и String.
Подробнее о контексте преобразования строк см. в п. 5.4.
Оптимизация конкатенации строк:Реализация может выбрать выполнение преобразования и конкатенации в один шаг, чтобы избежать создания и затем отбрасывания промежуточного Строковый объект. Чтобы увеличить производительность повторяющейся строки concatenation, компилятор Java может использовать класс StringBuffer или аналогичная техника для уменьшения количества промежуточных объектов String которые создаются путем оценки выражения.
Для примитивных типов реализация также может оптимизировать создание объекта-обертки путем преобразования непосредственно из примитива введите строку.
Оптимизированная версия на самом деле не сделает полное завершенное преобразование String.
Это хорошая иллюстрация оптимизированной версии, используемой компилятором, хотя и без преобразования примитива, где вы можете видеть, как компилятор меняет вещи на StringBuilder в фоновом режиме:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Этот код Java:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
Генерирует это - посмотрим, как два стиля конкатенации приводят к одному и тому же байт-коду:
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
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
// new StringBuilder(cip).append(ciop).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
Посмотрев на пример выше и как генерируется байт-код на основе исходного кода в данном примере, вы сможете заметить, что компилятор внутренне преобразовал следующий оператор
cip+ciop;
в
new StringBuilder(cip).append(ciop).toString();
Другими словами, оператор +
в конкатенации строк является эффективным сокращением для более подробного StringBuilder
-идиома.
Ответ 2
Это функция компилятора Java, которая проверяет операнды оператора +
. И на основе операндов он генерирует байтовый код:
- Для String он генерирует код для concat строк
- Для чисел, он генерирует код для добавления чисел.
Вот что говорит спецификация Java:
Операторы + и
-
называются аддитивными операторами. АддитивноеВыражение: МультипликативноеВыражение AdditiveExpression + MultiplicativeExpression AdditiveExpression - Мультипликативное выражениеОператоры-добавки имеют одинаковый приоритет и синтаксически левые ассоциативные (они группируются слева направо). Если тип операндом оператора
+
являетсяString
, тогда операция представляет собой конкатенацию строк.В противном случае тип каждого из операндов оператора
+
должен быть типом, который (§5.1.8) является примитивным числовым типом, или возникает ошибка времени компиляции.В каждом случае тип каждого из операндов двоичного оператора
-
должен быть тип, который является конвертируемым (п. 5.1.8), к примитивному числовому типу или ошибка времени компиляции.
Ответ 3
Как класс String переопределяет + оператор?
Это не так. Компилятор делает это. Строго говоря, компилятор перегружает оператор + для операндов String.
Ответ 4
Прежде всего (+) перегружен не переопределенным
Язык Java обеспечивает специальную поддержку для строки оператор конкатенации (+), который был перегружен для строк Java объекты.
-
Если операнд левой стороны - String, он работает как конкатенация.
-
Если операнд левой стороны - Integer, он работает как оператор сложения
Ответ 5
Язык Java обеспечивает специальную поддержку оператора конкатенации строк (+) и для преобразования других объектов в строки. Конкатенация строк реализуется с помощью класса StringBuilder
(или StringBuffer
) и его метода append
.
Ответ 6
Значение оператора +
при применении к String
определяется языком, как все уже написано. Поскольку вы, кажется, не находите это достаточно убедительным, подумайте об этом:
Ints, float и doubles имеют разные двоичные представления, и поэтому добавление двух ints - это другая операция с точки зрения манипуляции с битами, чем добавление двух float: для ints вы можете добавлять побиты, перенося бит и проверяя переполнение; для поплавков вы должны иметь дело с мантиссами и экспонентами отдельно.
Итак, в принципе "добавление" зависит от природы добавляемых объектов. Java определяет его для строк, а также для int и float (longs, double,...)
Ответ 7
Оператор +
обычно заменяется на StringBuilder
во время компиляции. Подробнее см. .