[윤성우의 열혈 Java 프로그래밍] Chapter 11 - 메소드 오버로딩과 String 클래스

Update:     Updated:

카테고리:

태그:

11-1. 메소드 오버로딩(Method overloading)

- 메소드 오버로딩의 조건

호출할 메소드를 찾을 때 다음 두 가지 정보를 참조하여 메소드를 찾게 된다.

  1. 메소드의 이름
  2. 메소드의 매개변수 정보(타입, 갯수)
class MyHome {  // 매개변수의 선언이 다르면 호출된 메소드의 구분이 가능하다.
    void mySimpleRoom(int n){ }
    void mySimpleRoom(int n1, int n2){ }
    void mySimpleRoom(double d1, double d2) { }

    /* 반환형은 호출할 메소드를 선택하는데 있어서의 판단 기준이 아니다.
    int simpleMethod(){ }
    double simpleMethod(){ }
    */
}

- 생성자도 오버로딩의 대상이 된다.

class Person {
    private int regiNum;    // 주민등록 번호
    private int passNum;    // 여권 번호

    Person(int rnum, int pnum){ // 매개변수의 갯수가 다름
        regiNum = rnum;
        passNum = pnum;
    }
    Person(int rnum) {
        regiNum = rnum;
        passNum = 0;
    }
}

class ConOverloading{
    public static void main(String[] args){
        Person choi = new Person(335577, 112233);    // 여권이 있는 경우
        Person park = new Person(335577);   // 여권이 없는 경우
    }
}

- 키워드 this를 이용한 다른 생성자의 호출

class Person {
    private int regiNum;    // 주민등록 번호
    private int passNum;    // 여권 번호

    Person(int rnum, int pnum){ // 매개변수의 갯수가 다름
        regiNum = rnum;
        passNum = pnum;
    }
    Person(int rnum){
        this(rnum,0);
    }
//    Person(int rnum) {
//        regiNum = rnum;
//        passNum = 0;
//    }
}

class ConOverloading{
    public static void main(String[] args){
        Person choi = new Person(335577, 112233);    // 여권이 있는 경우
        Person park = new Person(335577);   // 여권이 없는 경우
    }
}

this는 오버로딩 된 다른 생성자를 의미한다. 이 생성자는 단순히 초기화할 값을 전달받는 역할만 하고,
실제 초기화는 첫 번째로 정의된 생성자를 통해서 진행하는 형태가 된다.

- 키워드 this를 이용한 인스턴스 변수의 접근

image
여기서 this가 의미하는 것은 ‘이 문장이 속한 인스턴스’이다.

11-2. String 클래스

- String 클래스의 인스턴스 생성

String str1 = new String("Simple String");
String str2 = "Best String";

System.out.println(str1.length());  // println은 다양한 인자를 전달받을 수 있도록 오버로딩이 되어있다. 

- 문자열 생성을 위한 두 가지 방법의 차이점은?

앞서 보인 두 가지 문자열 생성 방법의 차이점을 알아보자!

class ImmutableString {
    public static void main(String[] args){
        // 문자열 생성 방법 1
        String str1 = "Simple String";
        String str2 = "Simple String";

        // 문자열 생성 방법 2
        String str3 = new String("Simple String");
        String str4 = new String("Simple String");
        
        if(str1 == str2)
            System.out.println("str1과 str2는 동일 인스턴스 참조");
        else
            System.out.println("str1과 str2는 다른 인스턴스 참조");

        if(str3 == str4)
            System.out.println("str3과 str4는 동일 인스턴스 참조");
        else
            System.out.println("str3과 str4는 다른 인스턴스 참조");
    }
}

image
참조변수를 대상으로 한 == 연산은 ‘참조변수의 참조 값’에 대한 비교 연산을 진행한다.

이러한 차이를 보이는 이유는..

String 인스턴스는 Immutable 인스턴스이다.

Immutable하다는 것은 값을 변경할 수 없다는 뜻이다.
즉, 문자열 인스턴스를 생성한 후에는 인스턴스가 소멸할 때까지 바꿀 수 없다.

이처럼 문자열 인스턴스는 데이터를 수정할 수 없는, 참조만 가능한 인스턴스이기 때문에
그 내용이 같을 경우 굳이 새로운 인스턴스를 생성할 필요가 없어진다.

앞의 str1과 str2처럼 하나의 인스턴스를 생성해서 이를 공유하는 방식으로 코드를 처리하면
이로 인해 생성되는 인스턴스의 수는 줄고 성능은 향상된다.

11-3. String 클래스의 메소드

- 문자열 연결시키기: Concatenating

public class StringConcat { // 두 문자열을 연결시킨 문자열을 결과로 얻는다.
    public static void main(String[] args) {
        String st1 = "Coffee";
        String st2 = "Bread";

        String st3 = st1.concat(st2);

        System.out.println(st3);    // CoffeBread
    }
}

- 문자열의 일부를 추출하기: Substring

public class SubString {    // 문자열의 뒷부분을 별도의 문자열로 추출할 수 있다.
    public static void main(String[] args) {
        String st1 = "abcdefg";

        String st2 = st1.substring(2);  // beginIndex ~ 끝까지 추출
        String st3 = st1.substring(2,4);    // beginIndex ~ endIndex 사이 추출

        System.out.println(st2);    // cdefg
        System.out.println(st3);    // cd
    }
}

- 문자열의 내용 비교: comparing

public class CompString {
    /**
     1. equals
     2. compareTo
     3. compareToIgnoreCase
     */

    public static void main(String[] args) {
        String st1 = "Lexicographically";
        String st2 = "lexicographically";
        int cmp1, cmp2;

        if(st1.equals(st2)) // 두 인스턴스가 지니는 문자열이 같으면 true, 다르면 false를 반환함
            System.out.println("두 문자열은 같음");
        else
            System.out.println("두 문자열은 다름");


        /*
        두 문자열의 내용이 일치하면 0
        호출된 인스턴스의 문자열(st1)이 인자로 전달된 문자열(st2)보다 앞서면 0보다 작은 값 반환
        호출된 인스턴스의 문자열(st1)이 인자로 전달된 문자열(st2)보다 뒤서면 0보다 큰 값 반환
         */
        cmp1 = st1.compareTo(st2);   // 두 문자열의 사전 편찬 상 순서를 비교함.

        if(cmp1 == 0)
            System.out.println("두 문자열은 일치합니다.");
        else if (cmp1 < 0)
            System.out.println("사전의 앞에 위치하는 문자: " + st1);
        else
            System.out.println("사전의 앞에 위치하는 문자: " + st2);


        /*
        사전 편찬 순서상 대문자는 소문자보다 앞에 위치한다.
        하지만 compareToIgnoreCase는 이름 그대로, 문자열 비교에 있어서 대소문자 구분을 하지 않는다.
        그 외에 부분에 대해서는 compareTo와 동일하다.
         */
        cmp2 = st1.compareToIgnoreCase(st2);

        if(cmp2 == 0)
            System.out.println("두 문자열은 같습니다.");
        else
            System.out.println("두 문자열은 다릅니다.");
    }
}

- 기본 자료형의 값을 문자열로 바꾸기

static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(double d)
static String valueOf(int i)
static String valueOf(float f)
static String valueOf(long l)

String 클래스에 정의되어 있는 위의 메소드들을 호출하면 기본 자료형의 값을 문자열로 바꿀 수 있다.
클래스 메소드이므로 다음과 같이 사용한다.

double e = 2.718281;
String se = String.valueOf(e);  // "2.718281"

- StringBuilder 클래스

String의 반복적인 인스턴스 생성은 프로그램의 성능을 저하시킨다.
문자열끼리의 연산은 빈번한 인스턴스의 생성을 야기시킬 수 있으므로 이를 방지하기 위해 StringBuilder 클래스를 사용한다.

StringBuilder 클래스는 내부적으로 문자열을 저장하기 위한 메모리 공간을 지닌다.
이 메모리공간은 String 클래스의 메모리 공간과는 다르게 문자를 ‘추가’하거나 ‘삭제’하는 것이 가능하다.
따라서, ‘수정하면서 유지해야 할 문자열’이 있다면 이 클래스에 그 내용을 담아서 관리하는 것이 효율적이다.

// StringBuilder 클래스의 메소드

public StringBuilder append(int i)  // 기본 자료형 데이터를 문자열 내용에 추가
public StringBuilder delete(int start, int end) // index start부터 end 이전까지 내용 삭제
public StringBuilder insert(int offset, String str) // 인덱스 offset의 위치에 str에 전달된 문자열 추가
public StringBuilder replace(int start, int end, String str)    // index start부터 end 이전까지 내용을 str으로 대체
public StringBuilder reverse()  // 저장된 문자열의 내용을 뒤집는다.
public String substring(int start, in end)  // 메모리 공간 안의 일부 내용만 가져다 String으로 반환
public StringBuilder toString() // 메모리 공간 안의 모든 내용을 string으로 반환

위의 매소드들은 무엇을 반환하는 것인가?

public class ReturnStringBuilder {
    public static void main(String[] args) {
        StringBuilder stb1 = new StringBuilder("123");
        StringBuilder stb2 = stb1.append(45678);

        System.out.println(stb1);
        System.out.println(stb2);


        // 인덱스 0~4까지의 문자 삭제
        stb2.delete(0, 5);

        System.out.println(stb1);
        System.out.println(stb2);

        // 참조 값의 비교
        if(stb1 == stb2)
            System.out.println("same instance");    // true
        else
            System.out.println("diff instance");
    }
}

다음 코드의 결과는 same instance가 출력된다.
즉, stb1과 stb2가 같은 인스턴스를 참조하게 된다.

image
따라서, 자바 컴파일러가 변환해 놓은 문장이 어떻게 처리되는지 알 수 있다.

- StringBuilder 클래스 이전에 사용되던 StringBuffer 클래스

StringBuffer 클래스는 자바 5에서 등장한 클래스이다.

StringBuffer와 StringBuilder는

  1. 생성자를 포함한 메소드의 수
  2. 메소드의 기능
  3. 메소드의 이름과 매개변수의 선언 위 세 가지가 일치한다. 이는 사실상 같은 클래스임을 의미한다.

그러나 차이점이 하나 있는데,

StringBuffer는 쓰레드에 안전하지만, StringBuilder는 쓰레드에 안전하지 않다.

StringBuffer -> 멀티 쓰레드 환경에서 안전, 속도 느림
StringBuilder -> 멀티 쓰레드 환경에서 안전하지 않음, 속도 빠름

Java lang 카테고리 내 다른 글 보러가기

댓글 남기기