JVM이 호출된 메소드를 찾을 때 참조하는 두 가지 정보가 있다.
즉, 메소드의 이름이 같더라도 매개변수 정보가 다르다면 서로 다른 메소드로 취급되고 이것이 메소드 오버로딩이다.
class AAA {
void simple(int p1, int p2) {...}
void simple(int p1, double p2) {...}
}
AAA inst = new AAA();
inst.simple(7, 'k');
이러한 경우 inst.simple(7, 'k')
는 위의 두 메소드 중 어떤 메소드가 실행이 될까?
메소드 호출 시에 자동 형변환 규칙이 적용되기 때문에, 메소드를 호출할 때에는 이러한 애매한 상황이 발생되지 않도록 해야 한다.
따라서, 어떤 메소드를 실행시킬지를 프로그래머가 명시적으로 알려주기 위해 직접 강제적 형변환을 시켜주자.
생성자 역시 메소드이기 때문에 생성자에서도 오버로딩 규칙이 적용된다.
class Person {
private int regiNum;
private int passNum;
Person(int rnum, int pnum) {
regiNum = rnum;
passNum = pnum;
}
Person(int rnum) {
regiNum = rnum;
passNum = 0;
}
...
}
"this"는 기본적으로 "이 인스턴스"라는 뜻을 가진다.
위의 Person
클래스에서 Person(int rnum)
을 좀더 보기 좋게 코드를 짤 수 있다.
Person(int rnum) {
this(rnum, 0);
}
이 때의 "this"는 해당 인스턴스의 다른 생성자를 지칭한다.
즉, "rnum"과 "0"을 받는 다른 생성자를 호출하게 된다.
"this"를 이용해서 인스턴스 변수에도 접근할 수 있다.
class SimpleBox {
private int data;
SimpleBox(int data) {
this.data = data
}
}
메소드에서 인자로 "data"를 받고 있고 이를 인스턴스 변수 "data" 저장을 해야 하는데 서로 구분하기 위해 "this"를 통해서 구분하고 있다.
this()
: 생성자 안에서만 사용할 수 있고, 해당 인스턴스의 또 다른 생성자를 호출this.
: 해당 인스턴스 변수 혹은 메소드에 접근String 클래스는 자바가 제공하는 표준 클래스로 우리가 만들 필요 없이 사용하기만 하면 된다.
String str1 = new String("Simple String");
String str2 = "The Best String";
"new"를 이용하거나 " "를 이용하면 String 클래스의 인스턴스가 만들어지고 참조값이 반환되어, 결과적으로 str2
는 String 인스턴스의 참조값을 저장하게 된다.
println()
메소드는 다양한 형태로 오버로딩되어 있기 때문에 다양한 인자를 받을 수 있다.
void println() {...}
void println(int x) {...}
void println(String x) {...}
String 인스턴스는 Immutable 인스턴스이다. 즉, 변경이 가능하지 않고, 값을 바꾸기 위해서는 새로운 인스턴스를 만들어야 한다.
String str1 = "Simple String";
String str2 = "Simple String";
String str3 = new String("Simple String");
String str4 = new String("Simple String");
이 경우에 str1
과 str2
는 같은 참조값을 가지고 같은 인스턴스를 가리키게 되고 str3
와 str4
는 서로 다른 참조값을 가지고 서로 다른 인스턴스를 가리킨다.
str1
과 str2
의 경우, 문제가 발생하지 않는 이유는 앞에서 설명한 Immutable 인스턴스의 성질 때문이다.
그러나, 만약에 내용은 같지만 다른 인스턴스를 만들고 싶다면 "new"를 이용해서 인스턴스를 만들면 된다.
.concat()
: 문자열 연결시키기, 새로운 문자열을 반환한다.
ex) String str3 = str1.concat(str2)
.substring()
: 문자열 일부 추출,
ex) str.substring(2)
: idx 2 이후의 문자열 반환
ex) str.substring(2, 4)
: idx 2~3의 문자열 반환
.equals()
: 문자열의 내용 비교, 같으면 true 반환
참고로 ==
는 참조값 비교
.compareTo()
: 문자열의 내용 비교, 같으면 0 반환
사전 순 앞서면 음수값, 사전 순 뒤서면 양수값 반환
.compareToIgnoreCase()
: .compareTo()
에서 대소문자 구분하지 않음
String.valueOf()
: 기본 자료형의 값을 문자열로 바꾸기String se = String.valueOf(7)
"funny" + "camp"
위의 연산으로 연결된 String이 반환되었던 것은 사실, 컴파일러에 의해서 .concat()
메소드로 변환되었던 것이다.
String birth = "<양>" + 7 + '.' + 16;
위의 연산은 .concat()
메소드로 진행되지 않는다.
만약, .concat()
메소드로 변환되어 진행되면 많은 String 인스턴스가 생성되고 사라질 것이다.
따라서, 컴파일러는 StringBuilder를 이용해서 문자열 결합을 최적화한다.
위 문장의 변환은 컴파일러에 의해 아래로 변환되어 진행된다.
String birth = (new StringBuilder("<양>").append(7).append('.').append(16)).toString();
처음에 생성된 StringBuilder 인스턴스에 각 문자들이 담기고 마지막의 toString()
에 의해 String 인스턴스가 반환된다.
append()
메소드는 호출된 메소드가 속한 인스턴스의 참조값을 반환하기 때문에 이어서 호출할 수 있다.
StringBuilder stbuf = new StringBuilder("123");
// 문자열 덧붙이기
stbuf.append(45678);
System.out.println(stbuf.toString());
// 문자열 일부 삭제
stbuf.delete(0, 2);
System.out.println(stbuf.toString());
// 문자열 일부 교체
stbuf.replace(0, 3, "AB");
System.out.println(stbuf.toString());
// 문자열 내용 뒤집기
stbuf.reverse();
System.out.println(stbuf.toString());
// 일부만 문자열로 반환
String sub = stbuf.substring(2, 4);
System.out.println(sub);
StringBuffer와 StringBuilder는 기능적으로는 완전히 동일하다.
즉, 다음 세 가지가 일치한다.
하지만, StringBuffer는 쓰레드에 안전하고 느린 반면에,
StringBuilder는 쓰레드에 안전하지 않고 빠르다는 특징이 있다.