본문 바로가기

Java 기본 문법 - 참조 서적 [이것이 자바다 - 한빛미디어]/3. 참조 타입

7. Java 자바 참조 타입 - 객체를 참조하는 배열, 배열 복사, 향상된 for 문

1. 객체를 참조하는 배열

 

기본 타입 (byte, char, short, int long, float, double, boolean) 배열은 각 항목에 직접 값을 갖고 있지만,

 

참조 타입 (클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 가지고 있다.

 

ex) String 은 클래스 타입 이므로, String[ ] 배열은 각 항목에 문자열이 아니라 String 객체의 주소를 가진다.

 

    String[ ] strArray = new String[3];

 

    strArray[0] = "Java";

    strArray[1] = "C++";

    strArray[2] = "C#";

 

    아래와 같이 메모리 영역에 저장된다.

 

String 타입 배열의 스택 / 힙 저장 방식

 

 

String[ ] 배열의 항목String 변수와 동일하게 취급되어야 한다.

 

따라서, String[ ] 배열 항목 간에 문자열을 비교할 때는 == 연산자 대신, equals( ) 메소드를 사용해야 한다.

( == 연산자는 객체 번지 비교!)

 

ex)

    String[ ] strArray = new String[3];

    strArray[0] = "Java";

    strArray[1] = "Java";

    strArray[2] = new String("Java");

 

    System.out.println( strArray[0] == strArray[1] );         // true 출력 : 같은 객체 참조

    System.out.println( strArray[0] == strArray[2] );         // false 출력 : 다른 객체 참조

    System.out.println( strArray[0].equals( strArray[2] ) );  // true 출력 : 문자열 동일

 

위의 코드는 아래와 같이 메모리 영역에 생성된다.

 

String 타입 배열도 String 타입 변수와 같은 동작을 한다.

 

public class ArrayReferenceObjectExam {
    public static void main(String[] args) {
    	String[] strArray = new String[3];
        
        strArray[0] = "Java";
        strArray[1] = "Java";
        strArray[2] = new String("Java");
        
        System.out.println(strArray[0] == strArray[1]);   // true
        System.out.println(strArray[0] == strArray[2]);   // false
        System.out.println(strArray[0].equals(strArray[2]));  // true
    }
}

 

 

2. 배열 복사

 

배열은 한 번 생성하면 크기를 변경할 수 없기 때문에

 

더 많은 저장 공간이 필요하게 되면 큰 배열을 새로 만들고 기존 배열의 항목 값들을 복사해야 한다.

 

배열 간의 항목 값을 복사하려면,  for 문을 사용하거나 System.arraycopy( ) 메소드를 사용한다.

 

- for 문을 사용한 배열 복사

public class ArrayCopyByForExam {
    public static void main(String[] args) {
    	int[] oldIntArray = { 1, 2, 3 };
        int[] newIntArray = new int[5];
        
        for(int i = 0; i < oldIntArray.length; i++) {
        	newIntArray[i] = oldIntArray[i];
        }
        
        for(int i = 0; i < newIntArray.length; i++) {
        	System.out.print(newIntArray[i] + ", ");
        }
    }
}

 

새로운 배열 newIntArray[ ] 배열 기본 초기값 0 (new 연산자로 생성) 이고,

 

복사되지 않은 항목의 자리는 배열 기본 초기값 0 이 그대로 유지된다.

 

newIntArray

1

2

3

0

0

 

 

- System.arraycopy( ) 메소드를 이용한 배열 복사

 

System.arraycopy( ) 메소드 호출 방법

 

System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

 

Object src : 원본 배열

 

srcPos : 원본 배열에서 복사할 항목의 시작 인덱스

 

Object dest : 새로운 배열

 

destPos : 새로운 배열에 붙여 넣을 시작 인덱스

 

length : 복사할 항목 개수

 

ex) 원본 배열(arr1), 새 배열(arr2), arr1의 모든 항목을 arr2에 복사하기

 

System.arraycopy( arr1, 0, arr2, 0 arr1.length );

 

ex) System.arraycopy

 

public class ArrayCopyExam {
    public static void main(String[] args) {
    	String[] oldStrArray = { "java", "array", "copy" };
        String[] newStrArray = new String[5];
        
        System.arraycopy(oldStrArray, 0, newStrArray, 0, oldStrArray.length);
        
        for(int i = 0; i < newStrArray.length; i++) {
        	System.out.print(newStrArray[i] + ", ");  // java, array, copy, null, null,
        }
    }
}

 

 

참조 타입 배열 (문자열) 일 경우, 배열 복사가 되면, 복사되는 값(항목의 값)이 객체의 번지이므로

새 배열의 항목은 이전 배열의 항목이 참조하는 객체와 동일하게 된다. (얕은 복사)

 

얕은 복사(shallow copy) : 참조하는 객체가 동일한 복사 ( 객체 번지 값만 복사 )

 

깊은 복사(deep copy) : 참조하는 객체를 별도로 생성하는 복사 ( 새로운 객체를 따로 생성한다 )

 

 

3. 향상된 for 문

 

반복 실행을 위해 카운터 변수와 증감식을 사용하지 않는다.

 

배열 및 컬렉션 항목의 개수만큼 반복하고 자동으로 for 문을 빠져 나간다.

 

향상된 for 문 실행 흐름

 

for 문의 괄호( ) 에는 배열에서 꺼낸 항목을 저장할 변수 선언, 콜론 ( : ), 배열을 나란히 작성한다.

 

for 문이 처음 실행될 때 ① 배열에서 가져올 첫 번째 값이 존재하는지 검사한다.

 

가져올 값이 존재하면, ② 변수에 저장한다.

 

그리고 ③ 실행문을 실행한다.

 

실행문을 모두 수행하고 나면, 다시 ① 배열에서 가져올 다음 값이 있는지 검사한다.

 

가져올 항목이 없으면 for 문은 종료된다. (반복 횟수는 배열의 항목 수가 된다.)

 

ex)

public class AdvanceForExam {
    public static void main(String[] args) {
    	int[] scores = {95, 71, 84, 93, 87};
        
        int sum = 0;
        for(int score : scores) {  // 배열 변수가 온다 ( 저장될변수 : 배열변수 )
        	sum = sum + score;
        }
        System.out.println("점수 총합 = "+sum");
        
        double avg = (double) sum / scores.length;
        System.out.println("점수 평균 = "+avg");
    }
}