[java] Reference 참조 타입, 배열, 열거

주소를 가리키는 Reference 참조 타입

java에서 참조 타입에 대해 알아봅니다.

🧩1. 데이터 타입 분류

변수의 메모리 사용

  • 기본 타입 변수 👉 실제 값을 변수 안에 저장
  • 참조 타입 변수 👉 주소를 통해 객체 참조
#기본 타입 변수 -> 스택(stack) 영역에 저장
int age = 25;
double price = 100.5;

#참조 타입 변수 -> 힙(heap) 영역에 저장
String name = "홍길동";
String hobby = "독서";

🧩2. 메모리 사용 영역

JVM이 사용하는 메모리 영역

  • 메소드 영역
    • JVM 시작할 때 생성
    • 로딩된 클래스 바이트 코드 내용을 분석 후 저장
    • 모든 스레드가 공유
  • 힙 영역
    • JVM 시작할 때 생성
    • 객체/배열 저장
    • 사용되지 않는 객체는 Garbage Collector가 자동 제거
  • JVM 스택
    • 스레드 별 생성
    • 메소드 호출할 때마다 Frame을 스택에 추가(push)
    • 메소드 종료되면 Frame 제거(pop) 

🧩3. 참조 변수의 ==, !=연산

변수의 값이 같은지 다른지 비교

  • 기본 타입 : byte, char, short, int, long, float, double, boolean
    • 변수의 값이 같은지 다른지 조사
  • 참조타입 : 배열, 열거, 클래스, 인터페이스
    • 동일한 객체를 참조하는지 다른 객체를 참조하는지 조사

🧩4. Null과 NullPointException

null(널)

  • 참조 타입의 기본 값은 null 입니다.
  • 변수가 참조하는 객체가 없을 경우 초기값으로 사용 가능합니다.
  • 참조 타입의 변수에만 저장 가능합니다.
  • null로 초기화된 참조 변수는 스택 영역 생성합니다.
  • ==, != 연산이 가능합니다.
    • null로 초기화된 경우 refVal == null 의 결과는 true 입니다.
    • 초기화 전에 refVal == null의 결과는 false 입니다. 

🧩5. String 타입

문자열을 저장하는 클래스 타입

  • 변수가 선언되면 stack에 '주소'가 저장되며, '홍길동' 실제 데이터는 heap에 저장됩니다.
String name;
name = "홍길동"
  • 문자열 리터럴 동일하다면 String 객체 공유합니다. 즉, 같은 데이터를 다른 이름의 변수에 저장할 수 있습니다..
  • new 연산자를 사용하여 String 객체를 생성하면, 힙 영역에 새로은 String 객체가 생성됩니다.

🧩6. 배열 타입

연속된 공간에 저장하는 자료구조

  • 같은 타입의 데이터를 연속된 공간에 저장하는 자료구조입니다.
  • 각 데이터 저장 위치는 인덱스를 부여해 접근합니다. 
int score1=81;
int socre2=82:                  <score 배열>
     .                     --------------------------
     .                    |81|82|               |75|
     .                     --------------------------
int score30=75;     <인덱스>  0  1                 29
                          배열이름[인덱스]로 접근  ex) score[0]

배열 선언

  • 배열을 사용하기 위해 우선 배열 변수를 선언합니다. 
#타입[] 변수;
int[] intArray;
double[] doubleArray;
String[] strArray;

#타입 변수[];
int intArray[];
double doubleArray[];
String strArray[];
  • 배열 변수는 참조 변수이므로, 배열이 생성되기 전 null로 초기화할 수 있습니다.
#배열 초기화 방법들
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] intArray1 = new int[] { 10, 20, 30, 40, 50 }; // 배열초기화 1
		int[] intArray2 = { 10, 20, 30, 40, 50 }; // 배열초기화 2

		int[] array3;
		array3 = new int[] { 10, 20, 30, 40, 50 }; // 배열초기화 3

		for (int i = 0; i < intArray1.length; i++) {
			System.out.println(intArray1[i]);
		}
	}

}
  • 다음과 같이 배열의 길이를 선언할 수도 있습니다.
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	    int[] intArray = new int[5];
	    intArray[0] = 10;
	    intArray[1] = 20;
	    intArray[2] = 30;
	    intArray[3] = 40;
	    intArray[4] = 50;

	    for (int i=0; i<intArray.length; i++) {
	    	System.out.println(intArray[i]);
	    }
	}

}

배열 길이

  • 배열의 길이를 확인할 수 있습니다. 
#타입[] 변수;
int[] intArray;
double[] doubleArray;
String[] strArray;

#타입 변수[];
int intArray[];
double doubleArray[];
String strArray[];
  • 배열 변수는 참조 변수이므로, 배열이 생성되기 전 null로 초기화할 수 있습니다.
#배열 초기화 방법들
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] intArray1 = new int[] { 10, 20, 30, 40, 50 }; // 배열초기화 1
		int[] intArray2 = { 10, 20, 30, 40, 50 }; // 배열초기화 2

		int[] array3;
		array3 = new int[] { 10, 20, 30, 40, 50 }; // 배열초기화 3

		for (int i = 0; i < intArray1.length; i++) {
			System.out.println(intArray1[i]);
		}
	}

}
  • 다음과 같이 배열의 길이를 선언할 수도 있습니다.
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	    int[] intArray = new int[5];
	    intArray[0] = 10;
	    intArray[1] = 20;
	    intArray[2] = 30;
	    intArray[3] = 40;
	    intArray[4] = 50;

	    for (int i=0; i<intArray.length; i++) {
	    	System.out.println(intArray[i]);
	    }
	}

}
  • 배열의 길이는 .length 로 확인 가능합니다.
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		  int[] intArray1= new int[] {10,20,30};
		  
		  System.out.println(intArray1.length);
		}
	}

배열 복사

  • 배열의 복사는 가벼운 복사(swallow cpoy)와 복제(deep copy)가 있습니다
    • 가벼운 복사는 주소만 복사 되며, 복제는 실제 값을 복사합니다.
  • 배열은 한번 생성하면 크기 변경이 불가능합니다.
  • 더 많은 저장공간이 필요하다면 보다 큰 배열을 새로 만들고 이전 배열로 부터 항목 값(주소)들을 복사해야합니다.
  • 배열 복사 방법은 다음과 같습니다.
    • System.arrayCopy() 메소드 이용
    • for 문 이용
    • Arrays 클래스 이용
  • 배열을 단순히 대입하게 되면, 하나의 실제 배열을 가리키는 주소만 복사가 됩니다.
    • array 배열의 값이 변하면 대입된 배열 copy_array 의 값도 변합니다.
    • 다음은 swallow  copy의 예입니다.
#배열을 단순히 대입하게 되면, 하나의 실제 배열을 가리키는 주소만 복사가 된다.
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = new int[] { 10, 20, 30, 40, 50 };
		int[] copy_array;

		copy_array = array;
		System.out.println(copy_array.length);

		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + ", ");
		}
		System.out.println();
		for (int i = 0; i < copy_array.length; i++) {
			System.out.print(copy_array[i] + ", ");
		}
	}
}
  • Deep copy 복제, System.arraycopy(src, srcPos, dest, destPos, length);
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = new int[] { 10, 20, 30, 40, 50 };
		int[] copy_array = new int[10];

		System.arraycopy(array, 0, copy_array, 0, array.length);
		array[0] = 100;

		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + ", ");
		}
		System.out.println();
		for (int i = 0; i < copy_array.length; i++) {
			System.out.print(copy_array[i] + ", ");
		}
	}
}
  • Deep copy 복제, for 문을 통해 배열 값을 하나 하나 대입
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = new int[] { 10, 20, 30, 40, 50 };
		int[] copy_array = new int[10];

		for (int i = 0; i < array.length; i++) {
			copy_array[i] = array[i];
		}

		System.out.println();
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + ", ");
		}
		System.out.println();
		for (int i = 0; i < copy_array.length; i++) {
			System.out.print(copy_array[i] + ", ");
		}
	}
}

  • 향상된 for 문 for (int 변수 : 배열) { } 을 이용해서 복제할 수도 있습니다.
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = { 10, 20, 30, 40, 50 };
		int[] copy_array = new int[10];
		int i = 0;
		for (int n : array) { // 향상된 for 문
			copy_array[i] = n;
			System.out.println(i);
			System.out.println(copy_array[i]);
			i++;
		}
	}
}

다차원 배열

  • 2차원 이상의 배열을 구성할 수 있습니다. 
  • 2차원 배열이 많이 사용되며, 수학의 행렬과 같은 자료 구조입니다. 
    • x, y 좌표로 표현되는 표형태입니다.
  • 자바는 1차원 배열을 이용하여 2차원 배열을 구현합니다.
  • ⭐️ darray.length 는 줄의 갯수 를 나타냅니다.
  • ⭐️ darray[0].length 는 0번째 줄의 배열 갯수를 의미합니다.​ 
public class referType1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[][] darray = new int[2][3];
		darray[0][1] = 1;
		darray[0][1] = 1;
		System.out.println(darray.length);
		System.out.println(darray[0].length);
		System.out.println(darray[1].length);

		int[][] varray = new int[2][];
		varray[0] = new int[3];
		varray[1] = new int[4];
		System.out.println(varray.length);
		System.out.println(varray[0].length);
		System.out.println(varray[1].length);

	}
}

🧩7. 열거 타입

한정된 값만을 갖는 데이터 타입

  • 한정된 값만을 갖는 데이터 타입이 열거 타입(enumeration type)입니다.
  • 열거 타입은 몇 개의 열거 상수 중에서 하나의 상수를 저장하는 데이터 타입입니다.
  • 열거 상수는 열거 타입의 값으로 사용되며, 관례적으로 모두 대문자로 작성합니다.
    • public enum Week { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY }
  • 열거 상수가 여러 단어로 구성될 경우 밑줄(_)로 처리합니다.
    • public enum Week { LOGIN_SUCCESS, LOGIN_FAILED }
    enum Color {RED,BLACK,WHITE,PURPLE,GREEN,YELLOW,GRAY}
    public class EnumTest {
    
    	public static void main(String[] args) {
    		Color color=Color.RED;
    
    	}
    
    }
    • Calendar를 이용해 오늘의 요일을 얻고 열거 타입 변수에 해당 열거 상수를 대입하는 예제입니다. 
    import java.util.Calendar;
     
    public class EnumWeekExample {
        public static void main(String[] args) {
            Week today = null;
            
            Calendar cal = Calendar.getInstance();
            int week = cal.get(Calendar.DAY_OF_WEEK);
            
            switch(week) {
                case 1:
                    today = Week.SUNDAY; break;
                case 2:
                    today = Week.MONDAY; break;
                case 3:
                    today = Week.TUESDAY; break;
                case 4:
                    today = Week.WEDNESDAY; break;
                case 5:
                    today = Week.THURSDAY; break;
                case 6:
                    today = Week.FRIDAY; break;                
                case 7:
                    today = Week.SATURDAY; break;        
            }
            
            System.out.println("오늘 요일: "+ today);
            
            if(today == Week.SUNDAY) {
                System.out.println("일요일에는 축구를 합니다.");
            } else {
                System.out.println("열심히 자바 공부합니다.");
            }
        }
    }
    

    댓글 쓰기

    0 댓글