ch05. 참조 타입

728x90

ch05. 참조 타입

05-1. 참조 타입과 참조 변수

[기본 타입과 참조 타입] : ‘저장되는 값’이 다르다.
기본 타입 변수: 변수에 실제 값을 저장
참조 타입 변수: 변수에 객체의 번지를 저장하고, 번지를 통해 객체를 참조

[메모리 사용 영역] : JVM은 운영체제에서 할당받은 메모리 영역을 세부 영역으로 구분

  • 메소드 영역 (모든 스레드가 공유)
    : JVM 시작할 때 생성
    : 코드에서 사용되는 클래스(.class)들을 클래스 로더로 읽어서 클래스 별로 정적 필드, 상수, 메소드 코드, 생성자 코드 분류 저장
  • 힙 영역 (객체와 배열 생성)
    : 여기에 생성된 객체와 배열은 스택영역 변수나 다른 객체의 필드에서 참조한다.
    : 만약 참조하는 변수, 필드 없으면 의미없는 객체가 되어 JVM은 자동 메모리 제거
  • JVM 스택 영역 (변수 생성 영역)
    : 메소드 호출 시 ‘프레임’ push
    : 메소드 종료 시 ‘프레임’ pop 동작 수행

[참조 변수의 ==, != 연산] : 번지 비교 연산

: 참조 타입 변수의 값은 ‘힙 영역의 객체 주소’라서

                       결국 번지 값을 비교하는 것이다. (즉, 동일한 객체 참조하는지 비교)

[null과 NullPointerException]

 

참조타입변수가 null값 가지면, 힙 영역의 객체를 참조하지 않는 상태

→ null값 가질 때는 스택 영역에 생성됨

예외 중 하나.

: null값 갖는 참조변수를 통해 (존재하지도 않는 객체)의 데이터나 메소드 코드 사용 시 발생

[String 타입] : 클래스 객체이므로 ‘참조 타입’

  • String 객체를 문자열 리터럴로 생성 시.
String name ="신용권";

String hobby = "자바" ;

: 변수는 String 객체 참조하고 있는 상태

: 변수는 스택 영역에 생성, 문자열 리터럴값은 힙 형역의 String객체에 생성

: 변수에는 String객체 번지 값이 저장됨

→ 동일한 문자열 리터럴로 객체 생성 시, 객체 공유함

→ new 객체 생성 연산자로 객체 생성 시,

                String name1 = new String("신용권"); //별도로 객체 생성한다.

[참조를 잃은 객체]

    String hobby = null; //참조하는 String객체 없다

        System.out.println(hobby.length()); 
                //참조변수 hobby가 참조하고 있는 객체의 문자열 길이를 알고 싶음

        String name = "홍자바"; //name변수는 String객체 참조하고 있다가

        System.out.println(name.length()); //정상 처리

                 name = null; //참조를 잃은 String 객체 -> JVM은 참조되지 않은 객체를 쓰레기 객체 취급하여 자동 메모리 제거

        System.out.println(name.length()); //비정상 처리 (nullPointerException)

: JVM은 참조되지 않은 객체를 쓰레기 객체 취급하여

                      (쓰레기 수집기) Garbage Collector 로 메모리에서 자동 제거 시킨다. 

                                                       →   자바의 메모리 자동 정리 기능

[문자열 비교] | equls() 메소드 사용

  • String객체가 달라도, 내부 문자열 값이 동일하면 T 리턴
public class StringEqualsExample {

    public static void main(String[] args) {
        //객체를 문자열 리터럴로 생성 

        String strVar1 = "신민철";
        String strVar2 = "신민철“ //동일한 문자열 리터럴로 String객체 생성 시, 객체 공유

        if(strVar1 == strVar2) { //참조타입 '번지 비교'
            System.out.println("참조 객체 동일 ");
        }else {
            System.out.println("참조 객체 불일치");
        }

        if(strVar1.equals(strVar2) ) { //내부 문자열 비교
            System.out.println("내부 문자열 동일");
        }

        //객체를 new연산자로 생성
        String strVar3 = new String("신민철");
        String strVar4 = new String("신민철"); //동일한 문자열 리터럴해도, new객체 별도 생성됨

        if(strVar3 == strVar4) { //참조타입 '번지 비교'
            System.out.println("참조 객체 동일 ");
        }else {
            System.out.println("참조 객체 불일치");
        }

        if(strVar3.equals(strVar4) ) { //내부 문자열 비교
            System.out.println("내부 문자열 동일");
        }

05-2. 배열

[배열] : 같은 타입의 데이터를 연속된 공간에 나열하여, 각 인덱스 부여한 구조

  • 반드시 배열은 동일한 타입의 데이터들만 모아 저장 가능하다.
  • 한 번 생성된 배열의 크기 변경 불가능

[배열 변수 선언]

         타입[  ] 변수 ;
  • 배열은 객체이므로 힙 영역에 생성되고, 배열 변수는 참조변수에 속한다.
  • 배열 변수가 선언되면, 배열 변수는 힙 영역의 배열 객체를 참조하는 상태가 된다.

[배열 객체 생성]

 **(1)<값 목록으로 배열 객체 생성>**

          타입[] 변수 = { 값1, 값2 ...};
  • 반드시 처음 변수 선언 시 값 목록 넣어야 한다. (변수 선언 후, 따로 값목록 배열 생성X)
  • 중괄호 {}는 배열 객체를 힙에 생성 후, 배열 객체의 번지를 반환한다,
  • 배열 변수에는 반환된 번지 저장되어 생성된 객체를 참조하는 상태된다.

✅(특정 인덱스 항목 값 변경) = 대입 연산자 사용

String[] names = {“A”, “B”, “C”};

names[1] = “D”;

✅(변수 선언 후/ 값 목록을 나중) : new연산자 사용 -> 값 목록 지정

타입[] 배열변수 = null;

배열변수 = new 타입[] {값1, 값2, 값3...};

→ 매개값이 배열인 메소드 호출 시,

“값 목록으로 배열 생성 동시에 매개값 사용 원하면”

         메소드의 매개값에 ( new 타입[] {값1, 값2, 값3...} ) 넣어 호출한다.

 **(2)<new연산자로 배열 객체 생성>** 

         타입[] 변수 = new 타입[길이];
  • 이 경우에는 배열 변수 선언 후에도 new연산자로 배열 생성 가능
  • new 연산자로 배열 처음 생성되면, 배열은 각 타입별 기본값으로 자동 초기화된다.

✅(특정 인덱스 항목에 새로운 값 저장) = 대입 연산자 사용

int scores = new int[3];

scores[1] = 83;

[배열 길이] | 배열변수.length

: 배열의 길이는 해당 배열의 length 필드에 저장되어 있기 때문에

         배열변수.length; //배열변수가 참조하고 있는 배열 객체의 length필드 읽어온다.

         for문 사용해서 배열 전체 루핑 시 유용하게 사용

[main() 메소드 매개값] | String[]args

public static void main (String[] args)

: JVM은 기본적으로 값 목록을 주지 않은 상태인 길이 0의 String배열 생성한 후, main()매개값으로 전달한다.

: main()메소드는 String[] args 매개변수 통해 입력된 배열 길이, 배열 항목값 알 수 있다.

**→ [이클립스에서 main()에 매개값 주는 방법]**

[RUN]-> [Run Configurations] : 실행 구성 -> [Arguments] -> [Program arguments]

  • 입력란에 공백으로 구분한 (String) 데이터값 넣으면 된다,
  • run -> 실행 구성 -> 인수 -> 프로그램 인수 : 입력란에 데이터값 입력

[다차원 배열]

**(1)<new연산자로 다차원 배열 객체 생성>**

      타입[][] = new 타입[길이][길이];

✅(행열 구조 배열 생성)

        **int[][] scores = new int[2][3];**

:scores 변수는 scores[2] 배열 객체 참조

:scores[0] 변수는 다시 길이3인 배열 객체 참조

:scores[1] 변수는 다시 길이3인 배열 객체 참조

✅(계단식 구조 배열 생성) : 행 인수만 주고, 열 인수를 나중에 결정

→ 이 형태의 배열 사용시, 배열의 정확한 길이 알고 인덱스 지정해서 사용할 것

int[][] scores = new int[2][];

scores[0] = new int[2];

scores[1] = new int[3];
**(2)<값 목록을 이용한 다차원 배열 객체 생성>**

     타입[][] 변수 = { {값1, 값2 }, {값3, 값4, 값5} };
//(1)new연산자로 배열 객체 생성 
        int[][] mathScores = new int[2][3]; //행열 구조
        for(int i = 0; i<mathScores.length; i++) {
            for(int j = 0; j<mathScores[i].length; j++    ) {

            System.out.println("mathScores["+ i + "]["+j+"] = " + mathScores[i][j]);
            }
        }
        System.out.println();

        int[][]    englishScores = new int[2][]; //계단식 구조
        englishScores[0] = new int[2];
        englishScores[1] = new int[3];
        for(int i = 0; i<englishScores.length; i++) {
            for(int j = 0; j<englishScores.length; j++    ) {
                System.out.println("englishScores["+i+"]["+j+"]="+englishScores[i][j]);
            }
        }
        System.out.println();

        //(2)값목록으로 배열 객체 생성
        int[][] javaScores = { {95,80}, {92,96,80}};
        for (int i=0; i<javaScores.length; i++) {
            for(int j=0; j<javaScores.length; j++) {
                System.out.println("javaScores=["+ i +"]["+j+"]"+ javaScores[i][j]);
            }

[객체를 참조하는 배열]

기본타입 배열은 배열 항목으로 실제 값을 갖는다.

참조타입 배열은 배열 항목에 참조하는 객체의 번지를 갖는다.

[String[] 배열]

: 배열 변수는 배열 객체 번지 갖고 참조하고 있다.

: 해당 배열 객체 속 내부 배열 항목값은 다시 객체 번지 갖는다.

: 따라서 참조타입의 배열 항목은 다시 참조 변수처럼 취급되어 각 주소값 갖는 객체 참조

따라서 String[] 배열 항목 간에 문자열 비교 == 연산자로 비교시, 객체의 번지가 비교된다.

                        equals(); 메소드 사용

[배열 복사]

: 배열 한 번 생성하면 크기 변경 불가능

: 더 많은 공간 필요할 경우, 더 큰 새로운 배열 만들어서, 이전 배열 항목값을 복사하여 옮김

**(1)<for 문으로 배열 항목값 복사>**
int[] oldArray = {1,2,3};

int[] newArray = new int[5];

for(int i=0; i<oldArray.length; i++) {

newArray[i] = oldArray[i];

}

(2)< System.arraycopy() 메소드 이용 배열 복사>

System.arraycopy( 원본배열, 복사시작위치, 대상배열, 복사될위치, 복사길이);

:참조타입배열이 복사되면, 복사되는 값은 다시 객체의 번지가 되므로

                           새 배열의 항목은 이전 배열 항목이 참조하던 객체와 동일하다.

[향상된 for문] : 배열과 컬렉션 쉽게 처리할 목적, 증감식X

for ( 변수 : 배열 ) {       // 배열 항목 개수만큼만 반복

                   //반복할 때마다 배열 각 항목 하나씩 순회하며 변수 저장하여 실행문 감

                   실행문;

                }

05-3. 열거 타입

   **열거 타입 : 몇 가지로 제한된 상수 만을 갖는 타입**

열거 타입 변수 : 열거 타입 내부의 열거 상수 1개만 올 수 있다.

[열거 타입 선언]

public enum 열거타입이름 {열거상수1, 열거상수2, ...열거상수5} ;

→ [이클립스에서 열거타입 생성] | [File – New – Enum]

패키지 입력란 : 열거 타입이 속할 패키지 이름

Enum Name 입력란 ; 열거 타입 이름 입력

→ 열거 타입 소스 파일 (.java)가 생성되어 저장되면 (.class) 바이트 코드 파일로 저장

→ 따라서 열거 타입 자체는 메소드 영역에 생성된다. (.class)파일로!

[열거타입 변수 선언] : 변수는 스택 영역에 생성

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

ex) Week today = Week.SUNDAY;

열거타입 Week는 {내부 열거상수} 최초 선언 시 → 메소드 영역에 생성

열거타입 변수 today 선언 시 → 스택 영역에 생성된다.

열거상수 Week.SUNDAY → 힙 영역의 Week 객체로 생성된다.

                    **(열거상수 = 객체)**

728x90

'Java > [문법]_Java(자바)' 카테고리의 다른 글

ch07. 상속  (0) 2021.08.03
ch06. 클래스  (0) 2021.08.02
ch04. 흐름 제어문 (조건문과 반복문)  (0) 2021.07.29
ch03. 연산자  (0) 2021.07.29
ch02. 변수와 타입  (0) 2021.07.28