[JAVA] 참조타입

msung99·2022년 3월 29일
0
post-thumbnail

책 정리

배열선언

// 잘못된 배열 선언 예시 : int[] arr;  arr = {1,2,3};  
//  int arr[] = new int[3];   arr = {1,2,3};
// => {덩어리}로 원소를 한번에 초기화할시에 선언과 동시에 초기화 하는게 아니고, 나중에 초기화하려고하면 애러 발생!

// 방법1) 선언과 동시에 초기화
1. int[ ] arr = {1,2,3,4,5};
2. int arr[ ] = {1,2,3,4,5};

// 방법2) 선언과 동시에 new로 크기 할당해놓고 나중에 값 할당시키기
// new 연산자로 배열을 선언시 각 배열의 타입의 기본값으로 초기화됨(ex. int배열 : 0, String배열 : null)
3. int[ ] arr = new int[5];   
4. int arr[ ] = new int[5];
arr[0] = 10; arr[1] =20; arr[2] = 30; arr[3] = 40; arr[4] = 50;

// 방법3) 선언만 해놓고 나중에 new로 배열 크기만 할당
5. int[] arr;
arr = new int[3];

6. int arr[];
arr = new int[3];

// 방법4) 선언만 해놓고 나중에 new 와 함께 초기화
// 배열 변수를 미리 선언한 후, 값 목록들이 나중에 결정되는 상황이라면 
// new 연산자를 사용해서 값 목록을 지정해주면 된다.
7. int[ ] arr;      
arr = new int[]{1,2,3,4,5};   

8. int arr[];
arr = new int[]{1,2,3,4,5};

// 메소드의 파라미터가 배열인 경우, 값 목록으로 배열을 생성함과 동시에
// add() 메소드의 매개값으로 사용하고자 할때는 반드시 new 연산자를 사용할것
9.  // int result = add({1,2,3}); => 에러발생
int result = add(new int[]{1,2,3}); 
(add함수 : int add(int[] scores){...} 

다차원 배열

배열 선언

  • 행의 크기는 반드시 지정해줘야한다.
  • 각 행에대한 1차원 배열 객체들이 힙에 각각 따로 저장되있는데, 그 객체들의 주소값을 저장하고 있는 1차원 배열이 힙에 따로 존재한다.
    그 주소들을 저장하고 있는 1차원 배열 객체를 바로 2차원 배열 참조변수가 가리키고 있다.
방법1) 행의 크기만 지정
int[][] arr = new int[3][];

arr[0] = new int[2];       => 2차원 배열의 각 행에대한 1차원 배열 객체를 3개 생성
arr[1] = new int[4];       => arr[1].length  도 호출가능(각 행의 배열은 1차원 배열이므로 당연히 length 호출가능)
arr[2] = new int[3];


방법2) 행과 열의 크기 모두 지정
int[][] arr = new int[2][3];


방법3) 선언과 동시에 초기화
int[][] arr = { {10,20}, {30,40,50,60}, {70,80,90} };

string 객체

  • 기본타입의 2차원 배열과 형태가 거의 동일.
    각 인덱스에 힙에 저장된 string 객체에 대한 주소값이 저장되어 있고, 이러한 string 배열 객체를 string 배열 참조변수가 가리키고 있다.
String[] arr = new String(4);
arr[0] = "java"; => arr[0] 과 arr[1] 은 힙에 있는 동일한 객체 참조
arr[1] = "java";  => arr[1] 과 arr[2] 는 서로 다른 객체 참조
arr[2] = new String("java");  => arr[2] 과 arr[3] 는 서로 다른 객체 참조
arr[3] = new String("java"); 

참조타입 배열의 복사

  • 얇은 복사, 깊은 복사모두 실행 결과는 기존 배열과 복사받은 배열 모두 각 인덱스가 동일한 참조 객체를 가리킨다.
    => 깊은 복사를 하더라도 새로운 배열 객체에다 기존 배열 객체의 각 인덱스에 들어있는 힙에 대한 주소값을 복사해 주는 것이므로, 결국엔 얇은 복사와 동일

System.arraycopy

System.arraycopy(인자1, 인자2, 인자3, 인자4, 인자5);

인자1 : 원본 배열
인자2 : 원본 배열에서 복사 시작할 위치(인덱스)
인자3 : 복사할 배열
인자4 : 복사할 배열에서 복사를 시작할 위치(인덱스)
인자5 : 복사할 개수(길이)

열거타입

// 열거 타입 선언
public enum Week{
  MONDAY,
  THUESDAY,
  WENDSDay,
  THURDSAY,
  FRIDAY
}

// 열거타입 변수 선언
1) Week today;  
2) Week today = Week.FRIDAY; // 열거타입 변수 선언과 동시에 열거상수 저장
  • 열거상수 실제 객체가 힙에 생성되며, MONDAY~SUNDAY 까지의 열거 상수는 각각 힙 영역에 있는 실제 객체를 참조하게 된다(가리키게 된다)
  • 열거 타입 변수 today 에 열거상수 FRIDAY 를 할당해주면(Week today = Week.FRIDAY;)
    이는 곧 열거상수가 가리키고 있는 실제 열거객체에 대한 주소를 넘겨주게 된 것이다.

=> 즉, 열거 상수 FRIDAY와 열거타입 변수 today 는 힙 영역의 실제 Week 열거객체를 같이 참조하게 된다.

today == Week.SUNDAY; => 동일한 실제 열거객체를 참조하므로 true가 리턴됨
Week week1 = Week.SATURDAY;
Week week2 = Week.SATURDAY;
System.out.println(week1 == week2)  // week1 와 week2는 모두 Week.SATURDAY 상수가 가리키는 
                                       동일한 Week 실제 객체를 참조하게 된다

Calendar 클래스

  • 컴퓨터의 날짜, 요일, 시간등을 얻을 수 있음.

메소드의 배열 리턴

int[] makeArray(){
  int temp[] = new int[4];
  return temp;
}

기본타입 배열 복사

  • 얇은 복사
    • 새로운 참조변수에게 동일한 배열 객체를 가리키도록 할당
ex)
int[] arr1;
arr2 = arr1;
  • 깊은 복사
    • 물리적으로 새로운 배열 객체를 만들어서 그곳에 값을 모두 복사시키는것
    • 반복문으로 깊은복사 가능
    • System.arraycopy() 사용해서도 가능
    • clone() 으로도 가능

기타타입 배열 복사

string 타입 배열 복사하기

  • string 타입 배열을 깊은복사하면, 기존 배열의 값들을 모두 복사해오는 것은 기본타입 배열 복사 방식과 똑같다.

  • 그러나 기본타입 배열 깊은 복사가 그냥 데이터 값을 복사하는 것이라면, 실제 string 객체를 가리키고 있는 메모리 주소를 복사하는 것이다.

    • 애초에 복사하고자 하는 기존 배열에는 문자열 자체가 저장되어 있는 것이 아니라, 실제 문자열 객체는 힙에 저장되어 있고, 이 문자열 객체를 가리키는 참조변수인 메모리 주소가 저장되어 있다.

결론적으로, 깊은 복사를 하더라도 새로운 배열에 깊은복사를 할시에 기존 배열에 저장되어 있던 메모리 주소가 복사하게 되어서( = 같은 메모리 주소 저장하게 되어서 ), 기존 배열과 새로운 배열은 둘 다 각 인덱스에서 동일한 string 객체를 가리키게 된다.
=> 최종 결과적으로는 얇은 복사가 이루어진것임

  • 하나의 실제 객체 참조 대상을 2개의 참조자가 참조하고 있는 상황이 된다!

for-each문

int[] scores = {1,2,3,4,5};

for(int score: scores){
  sum = sum + score;
}

열거형(enum 타입)

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

열거타입 선언

public enum 열거타입이름{ 열거상수들, ... }

ex)
public enum Week{ // 열거 타입 이름 : Week
  MONDAY,  // 열거 상수 7개
  TUESDAY,
  WENDESDAY,
  THURSDAY,
  FRIDAY,
  SATURDAY,
  SUNDAY
}
  • 열거 타입을 만들때 클래스 파일을 따로 만든다.
  • main함수가 들어있는 클래스 파일에 열거형을 같이 만들수도 있지만, 보통은 그렇게 잘 안함

열거타입 변수 선언

형태 : 열거타입 변수

Week today;
Week reservationDay;

열거 상수 값 저장

열거타입 변수 = 열거타입.열거상수

Week today = Week.SUNDAY;

지난 내용 복습 - 메소드,힙, 스택(스레드) 영역

메소드 영역 : 코드가 올라가는곳

스택 영역(스레드 영역) : 기본 타입변수, 참조 변수등이 올라가는 곳

힙 영역: 실제 객체 참조대상이 올라가는 곳


열겨형의 참조

  • 열겨형에 대한 참조변수는 메소드 영역에 만들어진다.

EX) Week 라는 열겨형 변수 안에 mon 이라는 애가 있는 경우

  • 메소드 영역에 mon에 대한 참조변수가 만들어지고, mon에 대한 실제 열거형 객체(참조 대상 객체)는 힙 영역에 만들어진다.
  • 즉, "mon" 이라는 문자열이 힙에 들어있고, 이 힙 영역의 객체를 가리키는 참조변수 mon은 메소드 영역에 있다.

따라서 Week.mon; 같은 경우 메소드 영역에 있는 참조변수 mon 이라고 생각하면 된다.

Week today = Wekk.SUNDAY;
=> today : 스택영역에 누적
SUNDAY : 메소드 영역에 만들었던 참조변수

열거 객체의 메소드

  • 열거 객체는 열거 상수의 문자열을 내부 데이터로 가지고 있다.

  • 객체이므로 몇 가지 메소드 보유

  1. name() : 열거 객체의 문자열을 리턴
  2. ordinal() : 열거 객체의 순번(순번은 0부터 시작)을 리턴
  3. compareTo() : 열거 객체를 순번 차이를 비교해서 순번 차이를 리턴
  4. valueOf(String name) : 주어진 문자열의 열거 객체를 리턴
  5. values() : 모든 열거 객체들을 배열로 리턴

예외처리

try-catch-finally 문

  • catch 문 여러개 선언가능

  • EX) try블록에서 0으로 나누기 예외가 발생하는 경우 (ex. 5를 0으로 나눔)

    • 거기에 대응하는 예외타입의 객체(이때는 예외 클래스
    • ArithmeticException 클래스를 기반으로한 객체가 생성) 가 생성
    • 이 객체를 catch 블록으로 전달함
try{
  예외가 발생할 가능성이 있는 실행문(try 블록)
}
catch(처리할 예외 타입 선언){ // try에서 던져진 예외 객체를 catch 블록에서 잡음
 예외 처리문(catch 블록)
}
finally{
  예외발생 여부와 상관없이 무조건 실행되는 문장 
}

예시

int dividened = 5;
int divisor = 0;

try{
  System.out.println(dividened / divisor);
  break;
catch(ArithmeticException e){
  System.out.println("0으로 나눌 수 없습니다. 다시 입력하세요");
}

예제 분석

예제 10

System.arraycopy(원본 배열, 원본 배열의 몇번째부터 복사를 할건지 숫자, 복사할 대상 배열, 복사할 배열의 몇번째 부터 복사할 건지 숫자, 몇개를 복사할 것인가 숫자)

ex)
System.arraycopy(oldStrArray, 0, newStrArray, 0, oldStrArray.length);
  • 복사하는 배열이 String 타입 배열이므로, 복사를 하면
    기존 배열과 복사당한 배열 모두 각 인덱스는 "java", "array", "copy" 라는 동일한 객체를 참조한다(가리킨다).

예제 12

동일한 패키지 안에 main 파일과 별개로 따로 enum 클래스 파일 만들어서 거기에다 열거형 정의할 것!

Calender 타입의 객체 DAY_OF_WEEK 를 만들어서, 그 객체에서 값 week 를 받아옴

예제 13

Week.SUNDAY 가 가리키고 있는 실제 열거 객체는 안에 문자열로 "SUNDAY" 을 가지고 있고, 이 객체에 대한 주소를 today 에다 넘겨줌

name() : 열거 객체안에 있는 문자열을 리턴

valueOf(문자열1) : 문자열1과 동일한 문자열을 가지고 있는 열거 객체의 주소를 리턴
ex) valueOf("SUNDAY")

0개의 댓글