Java에서 String이 클래스 일 때 + 연산자를 사용하여 String을 추가 할 수있는 이유는 무엇입니까? 에서 String.java
코드 나는이 연산자에 대한 구현을 찾을 수 없습니다. 이 개념이 객체 방향을 위반합니까?
답변
자바에서 다음과 같은 간단한 표현을 봅시다
int x=15;
String temp="x = "+x;
컴파일러는 내부적 "x = "+x;
으로 변환 하고 정수를 문자열에 “추가”하는 StringBuilder
데 사용 .append(int)
합니다.
문자열 변환을 통해 모든 형식을 문자열 형식으로 변환 할 수 있습니다.
프리미티브 유형 T의 값 x는 먼저 적절한 클래스 인스턴스 작성 표현식 (§15.9)에 인수로 제공하여 참조 값으로 변환됩니다.
- T가 부울 인 경우 new Boolean (x)을 사용하십시오.
- T가 char이면 new Character (x)를 사용하십시오.
- T가 byte, short 또는 int이면 new Integer (x)를 사용하십시오.
- T가 길면 new Long (x)를 사용하십시오.
- T가 float이면 new Float (x)를 사용하십시오.
- T가 double이면 new Double (x)를 사용하십시오.
그런 다음이 참조 값은 문자열 변환에 의해 문자열 유형으로 변환됩니다.
이제 참조 값만 고려하면됩니다.
- 참조가 널이면 문자열 “null”(4 개의 ASCII 문자 n, u, l, l)로 변환됩니다.
- 그렇지 않으면, 인수없이 참조 된 객체의 toString 메소드를 호출하는 것처럼 변환이 수행됩니다. 그러나 toString 메소드를 호출 한 결과가 널이면 문자열 “null”이 대신 사용됩니다.
toString 메소드는 기본 클래스 Object (§4.3.2)에 의해 정의됩니다. Boolean, Character, Integer, Long, Float, Double 및 String과 같은 많은 클래스가이를 재정의합니다.
문자열 변환 컨텍스트에 대한 자세한 내용은 §5.4를 참조하십시오.
문자열 연결 최적화 :
구현은 중간 문자열 개체를 생성 한 다음 폐기하지 않기 위해 한 단계로 변환 및 연결을 수행하도록 선택할 수 있습니다. 반복 문자열 연결 성능을 향상시키기 위해 Java 컴파일러는 StringBuffer 클래스 또는 유사한 기술을 사용하여 표현식 평가에 의해 생성 된 중간 문자열 객체의 수를 줄일 수 있습니다.프리미티브 유형의 경우 구현시 기본 유형에서 문자열로 직접 변환하여 랩퍼 오브젝트 작성을 최적화 할 수도 있습니다.
최적화 된 버전은 실제로 전체 랩핑 된 문자열 변환을 먼저 수행하지 않습니다.
다음은 컴파일러가 백그라운드에서 StringBuilder로 변경되는 것을 볼 수있는 프리미티브를 변환하지 않아도 컴파일러가 사용하는 최적화 된 버전을 잘 보여줍니다.
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
이 자바 코드 :
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
관용구 의 약칭입니다 .
답변
+
연산자 의 피연산자를 확인하는 Java 컴파일러 기능입니다 . 그리고 피연산자를 기반으로 바이트 코드를 생성합니다.
- String의 경우 문자열을 연결하는 코드를 생성합니다.
- 숫자의 경우 숫자를 추가하는 코드를 생성합니다.
이것은 Java 스펙이 말하는 것입니다 .
연산자 +를
-
추가 연산자라고합니다. AdditiveExpression : MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression-MultiplicativeExpression덧셈 연산자는 우선 순위가 동일하며 구문 적으로 왼쪽 연관되어 있습니다 (왼쪽에서 오른쪽으로 그룹화). (A)의 피연산자를 입력 할 경우
+
작업자는String
다음 동작은 문자열 연결된다.
그렇지 않으면 연산자의 각 피연산자
+
유형이 기본 숫자 유형으로 변환 가능한 (§5.1.8) 유형이어야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.모든 경우에 이진
-
연산자 의 각 피연산자 유형은 기본 숫자 유형으로 변환 가능한 유형 (§5.1.8)이어야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.
답변
String 클래스가 + 연산자를 어떻게 재정의합니까?
그렇지 않습니다. 컴파일러가 수행합니다. 엄밀히 말하면 컴파일러 는 String 피연산자에 + 연산자를 오버로드 합니다.
답변
우선 (+)가 오버로드되지 않은 오버로드
Java 언어는 Java 문자열 오브젝트에 과부하 된 문자열 연결 연산자 (+)에 대한 특별한 지원을 제공합니다.
-
왼쪽 피연산자가 문자열이면 연결로 작동합니다.
-
왼쪽 피연산자가 정수이면 덧셈 연산자로 작동합니다
답변
Java 언어는 문자열 연결 연산자 (+) 및 다른 객체를 문자열로 변환하는 데 특별한 지원을 제공합니다. 문자열 연결은 클래스 StringBuilder
또는 메소드를 통해 구현됩니다 .StringBuffer
append
답변
+
적용될 때 연산자 의 의미는 String
모든 사람들이 이미 작성한 것처럼 언어에 의해 정의됩니다. 충분히 설득력이없는 것으로 보이므로 다음 사항을 고려하십시오.
Int, float 및 double은 모두 서로 다른 이진 표현을 가지므로 두 개의 int를 추가하는 것은 비트 조작 측면에서 두 개의 float를 추가하는 것과 다른 작업입니다. 플로트의 경우 가수와 지수를 별도로 처리해야합니다.
따라서 원칙적으로 “추가”는 “추가 된”개체의 특성에 따라 다릅니다. Java는 문자열과 int 및 float (long, double, …)에 대해 그것을 정의합니다.