본문으로 바로가기

[JAVA ] 참조 타입(참조타입과 참조변수)

category Java 2022. 1. 30. 23:53

기본 타입

  • byte, short, char, int, long, float, double, boolean 타입 변수에 저장
  • 변수에 값 자체를 저장
  • 정수, 실수, 문자, 논리 리터럴 저장

 

참조 타입

  • 기본타입을 제외한 배열, 열거, 클래스, 인터페이스
  • 변수에 객체의 번지를 저장(==객체를 참조한다)

 

기본 타입 변수와 참조 타입 변수의 차이점

  • 기본타입 변수는 메모리 스택에 저장이 된다. 참조타입 변수는 힙에 저장된다.
  • 기본 타입으로 선언된 변수는 실제 값을 변수에 저장하지만
  • 참조 타입은 배열, 열거, 클래스, 인터페이스를 이용해서 선언된 변수는 메모리에 번지를 값으로 갖게 되어 번지를 메모리 스택에 저장
  • 번지를 통해 객체를 참조한다는 뜻으로 참조 타입이라고 부름

 

기본 타입 변수

int age = 25;
double price = 100.5;

참조 타입 변수

String name = "신용권";
String hobby = "독서";

스택에는 변수가 저장이 되고 힙에는 객체가 저장이 된다.

 

메모리 사용 영역

  • 자바는 메모리 사용영역을 메소드 영역 , 힙 영역 , JVM 스텍 영역 세가지의 메모리 사용 영역으로 구분해서 사용

메소드 영역

  • 주로 코드가 저장됨
  • 클래스별로 정적 필드 /상수 /생성자 / 메소드 코드 등을 분류해 저장한다
  • .java라는 소스 코드를 생성하고 컴파일하면 .class라는 바이트 코드파일이 생성됨 

 

힙 영역

  • 객체가 저장됨
  • 클래스로부터 생성된 객체들이 저장되는 영역이 힙 영역
  • 객체와 배열이 생성되는 영역

 

JVM 스택 영역

  • 변수가 저장됨
  • 바구니 모양으로 생긴 메모리
  • 여기에 프레임이라는 것들이 쌓여서 저장 됨
  • 메소드를 호출할 때마다 프레임이 추가되고, 메소드가 종료되면 해당 프레임이 제거
chst v1 = 'A'

if (v1 == 'A' {
	int v2 = 1000;
    double v3 = 3.14;
}

boolean v4 = true;

v1 프레임 생성 → v2와 v3 프레임에 생성이 되어 저장→ '}' 중괄호가 닫히면 중괄호 안에 있던 프레임은 제거가 됨

→ v1만 남음 →v4는 프레임 스택 영역에서 생성 됨→메소드 종료 후 v1과 v4모두 사라짐

  • 참조타입 변수는 스택  영역에 힙 영역에 생성된 객체의 주소 가짐
int[] scores = {10, 20, 30};

int[] scores이 배열은 참조타입이기 때문에 힙영역에 10,20,30이 저장되고 힙영역의 번지가 score이라는 배열객체에 저장됨.

 

  • 기본형 타입 변수의 값들은 stack영역에 저장
  • 참조형 타입 변수는 참조값만 저장된다. (이 참조값은 heap 영역에 존재하는 객체를 가리키는 역할 객체 주소 값 정도로라고 보면 됨)

 

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

  • 비교 연산자(==, !=)가 기본타입에서 사용되면 값을 비교하지만, 참조타입에서 사용되면 번지를 비교
  • 동일 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용
  • 참조 타입에 저장된 번지 값을 비교함 (==같은객체를 참조하는지 =!다른객체를 참조하는지 비교)
번지 == !=
같으면 true false
다르면 false true

위의 경우참조하는 객체가 같은지 다른지 비교

refVar1 == refVar2 // 결과: false
refVar1 != refVar2 // 결과: true
refVar2 == refVar3 // 결과: ture
refVar2 != refVar3 // 결과: false

이는 단순히 변수끼리의 값이 같으냐를 확인하는것이 아니라 참조하는 객체가 같은지를 확인함.

 

 

Null

  • 참조 타입 변수는 현재 객체를 참조하지 않는다는 뜻으로 null 값 가질 수 있음
  • 즉 객체를 참조하고 있지 않는 상태 
  • null로 초기화된 참조 변수도 스택 영역에 생성이 된다.

refVar1 == null //결과 : false
refVar1 != null //결과 : true
refVar2 == null //결과 : true
refVar2 != null //결과 : false

참조 타입 변수가 null 값을 가지는지 확인하려면 다음 코드와 같이 ==, != 연산을 수행

 

 

NullPointerException

  • 참조 변수가 null일때(객체를 참조하고 있지 않을때) 참조 변수를 통해 존재하지도 않는 객체를 사용하려고 할 경우 발생
  • Error (하드웨어의 문제 os의 문제 때문에 발생 에러같은 경우에는 개발자가 조취하기 힘듦 ) 랑 Exception (프로그램 실행하는 도중에 발생 프로그램 소스를 수정해서 익셉션이 발생하지 않게 할수 있음)을 구분해서 쓴다.
  • 참조 타입 변수가 null 상태에서 존재하지 않는 객체의 데이터나 메소드 사용할 경우 발생
  • 해당 참조 변수가 객체를 참조하도록 수정하여 해결
  • NullPointerException이 발생하면 변수가 null값을 갖고있는 상태인걸 인지하고 null값을 안갖게끔 어떤 객체를 대입을 한다던지 문자열을 대입을 해줘야 겠구나 생각 하면 됨. 
int[] intArray = null;       //특정 배열 값을 참조해주어 해결 ex)new int[3];
intArray[0] = 10;  //배열의 0번째 위치에 10을 저장하라는 뜻. NullPointerException 발생 배열이 없기때문에
String str = null;          //특정 문자열을 대입하여 해결 ex)"ABC" 하면 str.length() 결과값 3이나옴
System.out.println("총 문자수: " + str.length()); //str을 통해 스트링 객체length()라고 하는 메소드를 호출함.length()라고 하는 메소드는 스트링 객체가 있어야 사용할 수가 있기때문. NullpointerException 발생.

 

String 타입

  • String 변수에 문자열 리터럴을 대입할 경우, Sting객체로 생성되고 변수가 Sting객체를 참조(번지가 저장이됨)
Sting name = "신용권"
Sting hobby = "자바";
Sting name1 = "신용권"
Sting name2 = "신용권";

두 변수는 동일한 번지를 공유 (동일한 객체를 공유하기 때문)

 

New 연산자

  • 객체 생성 연산자
  • 힙 영역에 새로운 String 객체를 생성
Sting name1 = new String("신용권")
Sting name2 = new String("신용권");

  • 문자열 리터럴과 new 연산자로 생성된 객체 비교
String name1 = "신용권";
String name2 = "신용권";
String name3 = new String("신용권");

name1 == name2 : true

name1 == name3 : false

name2 == name3 : false

 

  • 즉 ,new를 이용하여 string객체를 만들게 되면 새로운 힙 영역에 저장이 되어 서로 같은 문자열 이어도 다른 힙 영역에 저장되기 때문에 다른 스트랭 객체로 인식.

 

 

문자열 비교

  • == : 번지 비교 (쓰지 않음 X)
  • equals(): 문자열 비교 (O)

== 연산자는 문자열의 번지를 비교하고, equals연산자는 문자열 자체를 비교함. 그래서 문자열을 비교할 때에는 주로 equals연산자를 사용.

boolean result = str1.equals(str2);
//         ( str1:원본 문자열)(str2:비교대상)
//str1과 str2의 문자열이 같으면 true를 리턴하고 str1과 str2의 문자열이 다르면 false리턴

str1과 str2가 서로 동일한 객체를 참조하고 있다.

new String(); 연산자를 이용해 선언 하면 서로 다른 참조를 함

 

  • String 변수 초기값으로 null 대입이 가능
    • String변수가 null 이라면 String 변수가 참조하는 객체가 없음을 의미.
String hobby = null;

처음부터 hobby라는 변수에 null 대입하는 경우

String hobby = "여행";
hobby = null;

어떤 문자열을 대입했다가 나중에 다시 null값 대입도 가능

 

참조를 잃은 String 객체는 쓰레기 수집기 (Garbage Collector) 통해 메모리에서 자동 제거됨

 

null 값의 length를 구하려 시도하자 NullPointerException 발생

 

  • 객체를 메모리에서 지우기 위해서는 위와 같이 null값을 대입해 변수에 저장된 참조를 끊어준다.
  • null값의 이전에 참조되어 있던 객체는 쓰레기 객체가 되고 쓰레기 수집기에 의해 메모리가 부족하거나 cpu가 한가할 때 메모리에서 제거가 됨

 

 

혼자공부하는 자바


코딩 공부하는 블로그
블로그 이미지 서하현 님의 블로그
VISITOR 오늘 / 전체