Java

[Java]참조 타입(이것이 자바다 Ch.5)(작성 중)

Woonys 2022. 5. 20. 19:10
반응형

5.1 데이터 타입 분류

  • 데이터 타입
    • 원시 타입(Primitive type)
      • 정수 타입
        • byte(1byte)
        • char(2byte)
        • short(2byte)
        • int(4byte)
        • long(8byte)
      • 실수 타입
        • float
        • double
      • 논리 타입
        • boolean
    • 참조 타입(Reference type)
      • 배열 타입(array)
      • 열거 타입(enum)
      • 클래스(class)
      • 인터페이스(Interface)
  • 변수: 스택에 생성
    • int, double → 직접 값을 저장
  • 객체: 힙에 생성
    • 클래스 변수 → 힙 영역의 객체 주소 값을 갖는다.
    • 주소를 통해 객체를 참조한다는 뜻에서 클래스 변수를 참조 타입(Reference type) 변수라고 한다.

5.2 메모리 사용 영역

JVM이 사용하는 메모리 영역

  • java.exe → JVM은 운영체제에서 할당받은 메모리 영역을 아래와 같이 세부 영역으로 구분해서 사용
    • 메소드 영역: 클래스 들어가 있음
    • 힙 영역: 객체와 배열 들어가 있음
    • 스레드(n개)
      • JVM 스택이 각 스레드별로 위치
        • JVM 스택 내에는 n개의 프레임 위치 → 스택 형태로 push/pop

힙 영역

  • 객체, 배열 생성되는 영역
  • 힙 영역에 생성된 객체, 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조
  • 참조하는 변수, 필드가 없다면 의미 없는 객체 → GC 발동! 쓰레기 객체를 힙 영역에서 자동 제거
    • 결국 참조하냐 안하냐로 GC가 발동하는 것!
  • 개발자는 객체 제거하기 위해 별도 코드 작성할 필요도 없고, 애초에 자바는 코드로 객체 제거하는 방법 제공하지 X

JVM 스택(stack) 영역

  • JVM 스택: 각 스레드마다 하나씩 존재 & 스레드 시작될 때 할당된다.
  • 자바 프로그램에서 추가적으로 스레드 생성 안하면 main 스레드만 존재 → JVM 스택도 하나.
  • 메소드 호출할 때마다 프레임을 추가(push) → 메소드가 종료되면 해당 프레임을 제거(POP)
  • 프레임 내부: 로컬 변수 스택
    • 기본 타입 / 참조 타입 변수 추가/제거(push/pop).
    • 변수가 이 영역에 생성되는 시점: 초기화될 때 → 최초로 변수에 값이 저장될 때
    • 변수는 선언된 블록 안에서만 스택에 존재, 블록 벗어나면 스택에서 제거
  • 기본 타입 변수: 스택 영역에 직접 값을 갖지만
  • 참조 타입 변수: 값이 아니라 힙 영역이나 메소드 영역의 객체 주소를 갖는다.
    • 배열 변수 scores: 스택 영역에 생성
    • but 실제 10, 20, 30을 갖는 배열은 힙 영역에 생성
  • 배열 변수 scores에는 배열의 힙 영역 주소가 저장!

5.3 참조 변수의 ==, != 연산

  • 기본 타입 변수의 ==, != ⇒ 변수 값이 같은지 아닌지만 조사
  • 참조 타입 변수 간의 ==, != ⇒ 동일 객체를 참조하는지 다른 객체를 참조하는지 비교
    • 참조 타입 변수 값 → 힙 영역 내 주소값! 결국 주소 값을 비교하는 것
    • 두 참조 변수가 동일한 주소값을 갖는다? → 동일한 객체를 참조한다는 의미

5.4 null과 NullPointerException

  • 참조 변수: 힙 영역 객체를 참조하지 않는다는 뜻으로 null 값 갖는다.
  • null 역시 초기값으로 사용 가능 → null로 초기화된 참조 변수는 스택 영역에 생성(힙에 생성될 이유 X 애초에 힙에 들어갈 게 없다.)

5.5 String 타입 → 문자열이 클래스구나!

  • 자바는 문자열을 String 변수에 저장 → 맨 처음에 String 변수 선언해야 한다.
String 변수;

변수 = "문자열"; // 문자열은 큰 따옴표로 감싼다. 그냥 문자(character)는 작은 따옴표
  • 문자열을 String 변수에 저장한다? → 틀린 말!
    • 문자열이 직접 변수에 저장되는 게 아니라, 문자열은 String 객체로 생성되고 변수는 String 객체를 참조하는 것!
      • 클래스 변수 자체는 스택 영역에 생성 → 변수 이름이 key, 문자열이 들어있는 힙 영역의 주소값을 value로 갖는다 & 문자열 리터럴은 힙 영역에 String 객체로 생성
  • 일반적으로 변수에 문자열 저장할 경우 문자열 리터럴 사용하나 new 연산자를 사용해서 직접 String 객체 생성시킬 수도 있음
  • new 연산자: 객체 연산자 → 힙 영역에 새로운 객체 만들 때 사용하는 연산자
  • // name1과 name2는 다른 String 객체를 참조 String name1 = new String("신용권"); String name2 = new String("신용권")); => 들어있는 문자열("신용권")만 같지 두 문자열이 힙 영역 내 전혀 다른 위치에 배치되어 있다.
  • 문자열 리터럴로 생성 vs new 연산자로 생성 비교
    • 문자열 생성 → == 연산 시 true
      • why? 동일 문자열 리터럴로 생성된 객체를 참조하기 때문
      • // name1 == name2 String name1 = "신민철"; String name2 = "신민철";
    • new 연산자로 생성 → false
      • why? new 연산자로 String 객체를 별도로 생성했기에 둘은 다르다.
      • // name1 != name2 String name1 = "신민철"; String name2 = new String("신민철");
    • 동일한 String 객체건 다른 String 객체건 상관없이 문자열 자체만 비교하고 싶으면 String 객체의 equals() 메소드를 사용해야 한다.

5.6 배열 타입

배열이란?

  • 사용 방식: 배열 이름 옆에 대괄호 [] 사용
  • score[인덱스값]

배열 선언

  • 배열 선언하려면 배열 변수(배열의 이름)을 선언해야 한다.
  • 선언 방식
    1. 타입[ ] 변수;
    2. int[] intArray; double[] doubleArray; String[] stringArray;
    3. 타입 변수[ ];
    4. int intArray[]; double doubleArray[]; String stringArray[];
  • 배열 변수: 참조 변수에 속함.
    • 배열 역시 객체이므로 힙 영역에 생성
    • 배열 변수는 힙 영역의 배열 객체를 참조
    • 참조할 객체 없으면 배열 변수는 null 값으로 초기화 → 스택에 위치

값 목록으로 배열 생성

  • 배열 항목에 저장될 값 목록 있으면 간단하게 배열 객체 생성 가능
데이터타입[] 변수 = {값0, 값1, 값2, ...};

// ex
String[] names = {"신용권", "홍길동", "감자바"};
  • 주의사항: 배열 변수 이미 선언한 후에는 다른 실행문에서 중괄호 사용한 배열 생성은 허용 X
타입[] 변수; // 여기서 변수만 먼저 선언하고
변수 = {값0, 값1, 값2, ...}; // 여기서 배열 생성하면 컴파일 에러 뜬다!
  • 만약 배열 변수를 먼저 생성하고 나중에 값 목록 넣어야 할 상황이라면 new 연산자를 사용해서 값 목록 지정해주면 오케이
String[] names = null; // 변수 선언하고
names = new String[] {값0, 값1, 값2, ...}; // 여기서 new 써서 값 채워넣고    

new 연산자로 배열 생성

  • 값 목록 갖고 있진 않으나 향후 값 저장할 배열 미리 만들려면? new 연산자로 배열 객체 생성(위와 달리 애초에 처음부터 new 연산자로 배열 객체 생성
  • 타입[] 변수 = new 타입[길이]; 변수 = new 타입[길이];
반응형