Iteger+String과 같이 JAVA에서 제공하는 "+" 연산자는 C++ 관점에서 볼 때 항상 JAVA가 이 "+" 연산자를 어떻게 오버로드하는지 알고 싶어서 String 클래스에 들어가서 살펴보았지만 거기에 는 어떤 계란이 발견되었으므로 JAVA가 어떻게 하는지 생각했습니다. JAVA가 "+ 연산자 오버로딩"을 구현하는 방법을 단계별로 분석해 보겠습니다.
예제
public class Example { public static void main(String[] args) { Integer a = null; String b = a + "456"; System.out.println(b); } }
이 프로그램은 매우 간단하며 Integer와 String의 "+" 연산식입니다. 실행 결과: null456
샘플 프로그램 디컴파일
명령:
javap -c Example
디컴파일한 결과는 다음과 같습니다.
Compiled from "Example.java" public class com.boyu.budmw.test.Example extends java.lang.Object{ public com.boyu.budmw.test.Example(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: aconst_null 1: astore_1 2: new #2; //class java/lang/StringBuilder 5: dup 6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 9: aload_1 10: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 13: ldc #5; //String 456 15: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 21: astore_2 22: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 25: aload_2 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 29: return }
분석해 보겠습니다. 주요 함수 부분:
0: 상수 null을 피연산자 스택에 푸시합니다.
1: 피연산자 스택에서 null을 팝하고 인덱스 1을 사용하여 지역 변수 a에 저장합니다.
2: 새로운 StringBuilder
5: 이전에 new에 의해 생성된 공간을 복사하여 피연산자 스택에 푸시
6: 초기화 호출
9: 저장 결과를 피연산자 스택에 추가
10: StringBuilder.append(java/lang/Object) 호출
13: "456"을 스택 맨 위로 푸시
15: StringBuilder .append(java/lang/String)
18: toString 함수 실행
위 분석을 통해 최종적으로 StringBuilder 객체를 먼저 생성한 다음 "+"를 생성하는 것을 볼 수 있습니다. 연산 기호는 모두 "+"를 수행하기 위해 StringBuilder.append()라고 합니다. 이는 위의 예제 프로그램이 실행 후 null456인 이유를 설명할 수 있습니다. 개체를 추가하면
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
이 호출되어 개체를 문자열로 변환합니다.
JAVA에서는 왜 연산자 오버로드를 지원하지 않나요?
C++처럼 클래스도 연산자 오버로드를 제한하는 기준이 없기 때문에 개인적으로 운영 및 유지 관리에 어려운 문제가 될 것 같습니다. 연산자 오버로딩은 모든 사람이 당연하게 여길 수 있습니다. 오버로딩은 의미론에 큰 차이를 일으키고 가독성을 심각하게 떨어뜨립니다. 따라서 Java에서 연산자 오버로딩을 제거하는 기능은 고급 객체 지향 특성과 매우 일치합니다. 그러므로 이 문제에 대해 깊이 생각하지 마십시오.
후기
개발 과정에서 자주 사용되는 것들이지만, 일반적인 개발 과정에서는 그렇게 깊이 파고들지 않을 수도 있습니다. 나중에 이러한 다양한 것들을 계속 탐색해 가면서 작은 사례가 발견되었습니다.