[Java] 객체 배열, 메소드 활용

최지수·2024년 6월 9일
post-thumbnail

📘객체 배열

자바에서는 기본 타입 데이터뿐 아니라, 객체를 원소로 하는 개체 배열도 만들 수 있다.

Circle [] c;  // Circle 배열에 대한 레퍼런스 변수 c 선언
c = new Circle[5];  // 레퍼런스 배열 생성
for (int i=0; i<c.length; i++) {  
    c[i] = new Circle(i);  // 배열의 각 원소 객체 생성
}

📌배열 선언 및 생성

객체 배열을 만들기 위해서는 다음의 3단계가 필요하다.

배열에 대한 레퍼런스 선언

다음은 Circle 클래스의 배열에 대한 레퍼런스 변수 c를 선언한다.

Circle [] c;

이 선언문은 레퍼런스 변수 c만 선언할 뿐, 배열을 생성하는 것은 아니다. 그러므로 다음과 같이 배열의 원소 개수를 지정해서는 안 된다.

Circle[5] c;  // 오류. 배열의 크기를 지정하면 컴파일 오류 발생

레퍼런스 배열 생성

두 번째로 5개의 레퍼런스를 원소로 하는 배열을 생성한다. 배열의 원소는 객체가 아니라 레퍼런스이다.

c = new Circle[5];  // Circle 객체에 대한 레퍼런스 5개 생성

이 코드의 실행 결과는 Circle 객체에 대한 레퍼런스 배열이 생성되며, 변수 c가 이를 가리킨다. Circle 객체들은 아직 존재하지 않는다.

객체 생성

이제 다음 코드를 이용하여 Circle 객체를 하나씩 생성하여 배열 c[]의 각 레퍼런스에 대입한다.

for (int i=0; i<c.length; i++) {
    c[i] = new Circle(i);  // i 번째 Circle 객체 생성
}

배열의 크기만큼 Circle 객체를 생성하여 레퍼런스 배열에 하나씩 대입한다. 이렇게 하면 비로소 Circle 객체 배열이 생성된다.


📌배열의 원소 객체 접근

배열 c의 i번째 객체에 접근하기 위해서는 c[i] 레퍼런스를 사용하면 된다. 다음 코드는 배열 c에 들어 있는 모든 Circle 객체의 면적을 출력한다.

for (int i=0; i<c.length; i++) {
    System.out.print((int)(c[i].getArea()) + " ");
}

이 코드의 실행 결과는 다음과 같다.

0 3 12 28 50


📘메소드 활용

📌메소드 형식

메소드는 클래스의 멤버 함수로서, 메소드 앞에 접근 지정자를 선언한다는 점을 제외하면 C/C++의 함수 작성법과 동일하다. 접근 지정자는 public, private, protected, 디폴트의 4가지 유형으로, 메소드가 다른 클래스에서 호출될 수 있는지 지정하기 위해 사용된다.

// public: 접근 지정자,  int: 리턴 타입, getSum: 메소드 이름
public int getSum(int i, int j) {  
    int sum;
    sum = i + j;  // 메소드 코드
    return sum;
}

📌인자 전달

자바의 메소드 호출시 인자 전달 방식(argument passing)은 '값에 의한 호출'(call-by-value)이다. 호출하는 실인자의 값이 복사되어 메소드의 매개 변수에 전달된다.

기본 타입의 값이 전달되는 경우

메소드의 매개변수가 기본 타입(byte, char, short, int, long, float, double, boolean)으로 선언된 경우, 호출자(caller)가 건네는 값이 매개변수에 복사되어 전달된다.

int n = 10;
increase(n);

increase(int m) 메소드가 호출되면, 매개변수 m이 생성되고 10으로 초기화된다. 그러고 나서 m 값을 1 증가시킨다. increase()에서 리턴하여 main() 메소드로 돌아오면 변수 n 값은 여전히 10으로 남아 있다.

객체가 전달되는 경우

메소드의 매개변수가 클래스 타입인 경우, 객체가 아니라 객체의 레퍼런스 값이 전달된다.

increase(pizza);

이 호출문에 의해 increase(Circle m)가 호출되면 매개변수 m이 생기고, pizza 변수에 저장된 값(레퍼런스)이 m에 복사되어, m은 pizza가 가리키는 객체를 함께 가리키게 된다. 그러므로 m.radius++;에 의해 radius는 11로 변경되고 increase()가 종료한 후에도 그대로 남는다. 메소드 호출 시 객체가 전달되는 경우, 객체에 대한 레퍼런스만 전달되지 객체가 통째로 복사되지 않는다.

public class ReferencePassing {
    public static void main (String args[]) {
        Circle pizza = new Circle(10);
        increase(pizza);
        System.out.println(pizza.radius); // 실행결과: 11
    }

static void increase(Circle m) {
    m.radius++;
}

배열이 전달되는 경우

배열이 메소드에 전달되는 경우도 객체 레퍼런스가 전달되는 경우와 동일하다. 배열이 통째로 전달되는 것이 아니며 배열에 대한 레퍼런스만 전달된다.

public class ArrayPassing {
    public static void main(String args[]) {
        int a[] = {1, 2, 3, 4, 5};
        
        increase(a);
        
        for (int i=0; i<a.length; i++) {
            System.out.println(a[i]+" "); // 실행결과: 2 3 4 5 6
        }
    }
    
    static void increase(int[] array) {
        for (int i=0; i<array.length; i++) {
            array[i]++;
        }
    }
}

main()에서 생성된 배열 a가 increase()에 전달된다. increase(int [] array)의 매개변수 array는 정수형 배열에 대한 레퍼런스로서 배열 a를 가리키게 되어 두 레퍼런스는 하나의 배열을 공유하게 된다. increase() 메소드에서 array 배열의 각 원소를 1씩 증가시키고 리턴한 후, main()에서 배열 a를 출력하면 변경된 값 2 3 4 5 6이 출력된다.


📌메소드 오버로딩

자바에서는 한 클래스 내에, 이름이 같지만 매개변수의 타입이나 개수가 서로 다른 여러 개의 메소드를 중복 작성할 수 있다. 이것을 메소드 오버로딩 혹은 메소드 중복이라고 부른다. 메소드 오버로딩은 자바 다형성의 한 경우이다. 여러 개의 메소드가 오버로딩되려면 다음 두 조건을 모두 만족하여야 한다.

  • 메소드 이름이 동일하여야 한다.
  • 매개변수의 개수나 타입이 서로 달라야 한다.

메소드의 리턴 타입이나 접근 지정자는 메소드 오버로딩과 관계없다.

메소드 오버로딩 성공 사례

다음은 2개의 getSum() 메소드가 정상적으로 오버로딩된 사례이다. 메소드 이름이 동일하고 매개변수의 개수가 서로 다르기 때문에, 두 메소드는 한 클래스 내에 공존하는데 아무 문제가 없다.

class MethodOverloading {  // getSum() 메소드의 정상적인 오버로딩 사례
    public int getSum(int i, int j) {
        return i + j;
    }
    public int getSum(int i, int j, int k) {
        return i + j + k;
    }
}

메소드 오버로딩 실패 사례

메소드 오버로딩은 자바 컴파일러에 의해 판단되며, 컴파일러가 이름이 같은 메소드들을 구분할 수 있으면 메소드 오버로딩이 성공한다. 다음 코드는 오버로딩이 실패한 경우이다.

class MethodOverloadingFail {  // 메소드 오버로딩이 실패한 사례
    public int getSum(int i, int j) {
        return i + j ;
    }
    public double getSum(int i, int j) {
        return (double)(i + j);
    }
}

앞의 코드에서 2개의 getSum() 메소드의 매개변수 개수와 타입이 모두 같다. 그러므로 이 두 메소드는 호출자의 입장에서 구분할 수 없으며 자바 컴파일러는 컴파일 오류를 발생시킨다. 혹은 독자들이 메소드의 리턴 타입이 서로 다르니 두 메소드가 서로 다른 것이라고 생각할 수 있겠지만, 리턴 타입은 메소드를 구분하는 기준으로 사용하지 않는다.

profile
오늘보다 내일 더 성장하는 개발자🌱

0개의 댓글