6 분 소요

1. 참조 타입과 참조 변수

1-1. 기본 타입과 참조 타입

  • 기본 타입 변수 : 실제 값을 변수 안에 저장

    • byte, char, short, int, long, float, double, boolean

      ex) int age = 25;

  • 참조 타입 변수 : 메모리의 번지를 변수 안에 저장

    • 배열, 열거 클래스, 인터 페이스 변수

      ex) String name = “혼공컴운”;

1-2. 메모리 사용 영역

  • JVM은 운영체제에서 할당 받은 메모리 영역(Runtime Data Area)을 다음과 같이 세부 영역으로 구분해서 사용한다

image

출처 : 혼자 공부하는 컴퓨터 구조 + 운영체제 p.166

  • 메소드 영역
    • JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역
    • 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스 별로 정적 필드와 상수, 메소드 코드, 생성자 코드 등을 분류해서 저장한다.
  • 힙 영역
    • 객채와 배열이 생성되는 영역
      • 여기에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조
      • 만일 참조하는 변수나 필드가 없다면 의미 없는 객체자 되기 때문에 JVM이 이것을 쓰레기로 수집하고 쓰레기 수집기를 실행시켜 자동으로 제거한다.
      • 쓰레기 수집기(garbage collector)

        ➡ 메모리 관리 기법 중 하나.

        ➡ 자바에선 JVM의 쓰레기 수집기를 이용해 자동적으로 사용하지 않는 객체를 메모리에서 제거한다.

        ✔️ 객체를 제거하기 전 수행하고 싶은 일이 있을 때

        ➡ 쓰레기 수집기가 객체를 제거하기 전 중요한 데이터를 저장하고 싶을 때, 클래스 내에 객체 소멸자(finalize())를 재정의하여 객체가 소멸될 때 실행할 코드를 입력할 수 있다.

  • JVM 스택 영역

    • 메소드를 호출할 때마다 프레임을 추가하고 메소드가 종료되면 해당 프레임을 제거하는 동작을 수행한다.
    • 프레임 내부에는 로컬변수 스택이 있는데, 기본 타입 변수와 참조 타입 변수가 추가되거나 제거된다.
    • 스택 영역
      • 변수가 생성되는 시점은 초기화(최초로 변수에 값이 저장)될 때이다.
      • 변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 제거된다.
char v1 = 'A';

if (v1 == 'A'){
    int V2 = 100; // v2, v3은 if 블록 내부가 실행되고 있을 때만 스택 영역에 존재하고 블록을 빠져나가면 소멸됨.
    double v3 = 3.14;
}
boolean v4 = true;

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

  • 참조 타입 변수들 간의 ==, != 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는 지 알아볼 때 사용
    • 동일한 번지 값을 갖고 있다면, 동일한 객체를 참조하는 것.

1-4. null과 NullPointerException

  • null

    • 참조 타입 변수가 객체(힙 영역)를 참조하지 않는다는 의미의 값
    • null값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 저장된다.
    • 참조 변수가 null을 가지고 있을 경우
      • 참조 객체가 없으므로 변수를 통해 객체 사용 불가
  • 예외 : 프로그램 실행 도중에 발생하는 오류

  • NullPointerException

    • 참조 변수를 사용하면서 가장 많이 발생하는 예외

    • 참조 타입 변수를 잘못 사용하면 발생

      • null 상태에서 있지도 않은 객체의 데이터(필드)나 메소드를 사용하는 코드를 실행하면 발생
      int[] intArray = null; // 참조 변수(배열)
      intArray[0] = 10; //NullPointerException 발생 -> intArray 변수가 참조하는 배열 객체가 없기 때문
          
      String str = null; // 참조 타입(클래스)
      System.out.println(str.length()); //NullPointerException 발생 -> str 변수가 참조하는 String 객체가 없기 때문
      
    • NullPointerException 해결법 : 참조 변수를 추적해서 객체를 참조하도록 수정

1-5. String 타입

String name; // String 변수 우선 선언
name = "신용권"; // 큰따옴표로 감싼 문자열 리터럴을 대입해 String 변수에 문자열 저장
String hobby = "자바"; // 변수 선언과 동시에 문자열 저장
  • 문자열을 String 변수에 저장한다는 말은 엄밀히 말해 틀린 표현이다.

    • 문자열이 직접 변수에 저장되는 것이 아닌 String 객체로 생성되고 변수는 String 객체를 참조하기 때문
    • 하지만 일반적으로 String 변수에 저장한다고 표현한다.
  • 자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 되어 있다.

  • new 연산자(객체 생성 연산자)

    • 힙 영역에 새로운 객체를 만들 때 사용하는 연산자
    • 변수에 문자열을 저장할 경우에 문자열 리터럴을 사용하지만 new 연산자를 사용해 직접 String 객체 생성 가능
    String name1 = new String("신용권");
    String name2 = new String("신용권");
    //name1 과 name2는 서로 다른 String 객체를 참조한다.
    
    • 동일한 문자열 리터럴로 String 객체를 생성했을 경우 ‘==’ 연산 결과 ➡ true
    • new 연산자로 String 객체를 생성했을 경우 ‘==’ 연산 결과 ➡ false
  • 내부 문자열을 비교하고 싶을 때

    • String 객체의 equals() 메소드 사용
    boolean result = str1.equals(str2)
    
  • 더 이상 String 객체를 참조하고 싶지 않을 때

    String hongong = "혼공컴운"; // String 객체 참조
    hongong = null; // String 객체 참조 X
    
    • 참조를 잃은 String 객체는 쓰레기 취급하고 쓰레기 수집기를 구동시켜 메모리에서 자동 제거한다.

2. 배열

2-1. 배열(참조 변수)

  • 데이터를 연속된 공간에 나열하고, 각 데이터에 인덱스를 부여해 놓은 자료구조
    • 이러한 성질 때문에 중간 인덱스의 값을 삽입하거나 삭제하기 어렵고, 선언 후 배열의 인덱스 수를 늘릴 수 없다.
  • 같은 타입의 데이터만 저장할 수 있다.
    • 만약 다른 타입의 값을 저장하려고 하면 타입 불일지(Type mismatch) 컴파일 에러 발생
  • 인덱스
    • 0에서부터 “문자열(혹은 배열) 길이 -1”까지의 번호를 매긴 것.
    • 배열과 같은 선형 자료구조는 인덱스로 원소에 접근할 수 있다.
  • 열거 타입(enumeration type)

    • 한정된 값만을 갖는 자료형

      enum Week{
      	SUNDAY, MUNDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY //열거 상수
      }
      

2-2. 배열 선언

  • 배열을 사용하기 위해 배열 변수를 선언해야한다.
  • 배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체 참조

    • 만일 참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있다.
    • 배열 변수가 null값을 가진 상태에서 변수[인덱스]로 값을 읽거나 저장하게 되면 NullPointerException 발생
//배열 선언
int[] intArray; //형식1
int intArray[]; //형식2

int[] intArray = null; //NullPointerException

2-3 배열 생성

  • 배열 객채 생성 ➡ 값 목록 이용 or new 연산자를 이용
  • {}는 주어진 값들을 항목으로 가지는 배열 객체를 힙에 생성하고, 배열 객체의 번지를 리턴한다.
    • 배열 변수는 리턴된 번지를 저장함으로써 참조가 이루어진다.
// 배열 생성
타입[] 변수 = {v1, v2 ,v3, ...}; // 값 목록으로 배열 생성

//오류
타입[] 변수;
변수 = {v1, v2, v3, ...}// 배열 변수 선언 후 다른 실행문에서 중괄호 사용한 배열 생성 허용X
------------------------
// 배열 변수를 미리 선언한 후 값 목록들이 나중에 결정되는 상황일 때
변수 = new 타입[] = {v1, v2, v3,...}; // new 연산자를 이용한 배열 생성

// 배열 변수를 미리 선언한 후 new 연산자로 배열 생성 
타입[] 변수 = null;
변수 = new 타입[길이] 

// 배열 길이
int[] intArray = {10, 20, 30};
int num = intArray.length;]
  
//배열 복사
System.arraycopy(arr1, 0, arr2, 0, arr1.length)
  
// 향상된 for문
for (타입 변수 : 배열){
  실행문
}
// 다차원 배열(2x3 행렬)
int[][] scores = new int[2][3];

2-4 확인 문제

  1. 배열을 생성하는 방법으로 틀린 것

    • int[] array; array ={1, 2, 3};

      배열 변수 선언 후 다른 행문에서 중괄호 사용한 배열 생성 허용X

  2. 배열의 기본 초기값에 대한 설명으로 틀린 것

    • boolean 타입 배열 항목의 기본 초기값은 true이다.

      ➡ true가 아닌 false이다.

  3. 배열 길이

    ➡ array.length = 3

    ➡ array[2].length = 5

  4. for문을 이용해서 배열의 항목에서 최대값 구해보기

    **<코드>**

    public class Main {
        public static void main(String[] args) {
            int max = 0;
            int[] array = {1, 5, 3, 8, 2};
    				// 코드 작성 구간
            for (int i = 0; i < array.length; i++){
                if (array[i] > max){
                    max = array[i];
                }
            }
          	//
            System.out.println("max: " + max);
       
        }
    }
    

    **<결과>**

    image

  5. 중첩 for문을 이용해서 주어진 배열의 전체 항목의 합과 평균값 구해보기

    **<코드>**

    public class Main {
        public static void main(String[] args) {
            int[][] array = {
                    {95, 86},
                    {83, 92, 96},
                    {78, 83, 93, 87, 88}
            };
       
            int sum = 0;
            double avg = 0.0;
               
            //코드 작성 구간
            int cnt = 0;
            for(int i = 0; i < array.length; i++){
                for(int j = 0; j < array[i].length; j++){
                    sum += array[i][j];
                    cnt++;
                }
            }
            avg = (double)sum / (double)cnt;
            // 
            System.out.println("sum: " + sum);
            System.out.println("avg: " + avg);
        }
    }
    

    **<결과>**

    image

  6. 실행결과를 보고 코드 작성해보기

​ **<코드>**

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        boolean run = true;
        int studentNum = 0;
        int[] scores = null;
        Scanner scanner = new Scanner(System.in);

        while(run){
            System.out.println("----------------------------------------------");
            System.out.println("1.학생수 | 2.점수입력 | 3.점수리스트 | 4.분석 | 5.종료");
            System.out.println("----------------------------------------------");
            System.out.print("선택> ");

            int selecNo = Integer.parseInt(scanner.nextLine());

            if (selecNo == 1){
                // 코드 작성
                System.out.print("학생수> " );
                studentNum = Integer.parseInt(scanner.nextLine());
            }
            else if(selecNo == 2){
                // 코드 작성
                scores = new int[studentNum];
                for(int i = 0; i < scores.length; i++){
                    System.out.print("scores["+ i + "]> ");
                    scores[i] = Integer.parseInt(scanner.nextLine());
                }
            }
            else if(selecNo == 3) {
                // 코드 작성
                for (int i = 0; i < scores.length; i++) {
                    System.out.println("scores[" + i + "]> " + scores[i]);
                }
            }
            else if(selecNo == 4){
                // 코드 작성
                int max = -1000000;
                int sum = 0;
                double avg = 0.0;

                for(int i =0; i < scores.length; i++){
                    if (scores[i] > max){
                        max = scores[i];
                    }
                    sum += scores[i];
                }
                avg = (double)sum / (double)scores.length;
                System.out.println("최고 점수: " + max);
                System.out.println("평균 점수: " + avg);
            }
            else if(selecNo == 5){
                run = false;
            }
        }
        System.out.print("프로그램 종료" );
    }
}

​ **<결과>**

image

댓글남기기