우리는 지금까지 저장한다는 표현을 사용하였다.
여기서 참조타입과 기본타입의 차이를 알 수 있다.
아래 표를 통해 참조타입과 기본타입을 알아보자.
기본타입 종류 | 참조타입 종류 |
byte, char, short, int, long, float, double, boolean | 배열, 열거, 클래스, 인터페이스 |
기본타입은 주어진 값을 변수에 저장을 합니다.
참조타입은 주어진 값이 저장 된 메모리의 주소를 저장합니다.
이것을 이해하기 위해선 우선 stack과 heap 영역에 대한 이해가 필요합니다.
해당 stack과 heap영역에 대한 글은 링크를 통해 배워봅시다.
2022.03.02 - [IT Program/Java Basic] - 스택(stack) & 힙(heap) 영역 설명, 예시
스택(stack) & 힙(heap) 영역 설명, 예시
스택 영역 함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역 스택 영역의 크기는 컴파일 시에 결정 스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸 이렇
dongwoonew.tistory.com
기본타입과 참조타입의 차이점을 알아봅시다.
int wesley = 30;
String harry = "tistory";
int는 기본타입, String은 참조타입입니다.
그렇다면 해당 코드는 어떤 차이가 있을까.
스택 영역과 힙 영역으로 표현해봅니다.
스택영역 stack | 힙영역 heap |
기본타입 wesley = 10 | String 객체의 주소값 = 24414 tistory (주소에 저장되어있는 값) |
참조타입 harry = {24414(주소값을의미)} |
해당 표에 대해 설명해보겠습니다.
stack 영역에서 기본타입인 wesley라는 변수명에는 10이 직접 저장이 됩니다.
stack 영역에서 참조타입인 harry라는 변수명에는 주소값이 저장이 되게 됩니다.
24414는 제가 임의로 주소값을 표현한겁니다.
heap 영역에서 String 객체의 주소값 24414에 tistory를 저장하게 됩니다.
이를 인지하고 참조타입의 값을 찾아갈 때를 예시를 들어보겠습니다.
알아보기 편하게 작성하였다는 점 인지 부탁드리겠습니다.
String wesley = "tistory";
String harry = "tistory";
String snape = new String("tistory");
if(wesley == harry) {
System.out.println("wesley와 harry는 같은 주소값을 가지고 있다.");
}
if(harry == snape) {
System.out.println("harry 와 snape는 같은 주소값을 가지고 있다.");
}
if(wesley == snape) {
System.out.println("wesley 와 snape는 같은 주소값을 가지고 있다.");
}
해당 코드의 결과를 먼저 살펴보겠다.
우리는 코드를 통해 wesley와 harry와 snape는 tistory라는 값을 가지고 있다는 것을 알 수 있다.
하지만 코드의 실행 결과는 우리의 생각처럼 나오지 않는다.
이유는 무엇일까?
그 이유인 즉슨 참조변수는 같은 값에 대해 (==) 을 통해 검사 하는 것이 아닌
주소값을 비교하기 때문이다.
참조변수는 위의 코드를 보고 순서를 예를 들어보겠다.
참조변수에서 ==은 주소값을 비교한다.
String wesley = "tistory";를 실행 했을때 아래와 같은 행위를 한다. tistory라는 String객체가 heap 영역에 존재하는지 검사 없을시 String객체에 tistory 생성 wesley에 heap영역의 String객체 tistory가 저장되어 있는 주소값 저장 |
String harry = "tistory";를 실행 했을때 아래와 같은 행위를 한다. tistory라는 String객체가 heap 영역에 존재하는지 검사 존재할 경우 String객체 tistory가 저장되어있는 주소값 harry에 저장 |
String snape = new String("tistory");를 실행 했을때 아래와 같은 행위를 한다. new 연산자를 통해 heap 영역에 String타입의 "tistory"객체를 생성 snape에 해당하는 주소값을 저장 |
이 과정을 본다면 if문이 왜 저런결과가 나오는지 알 수 있다.
wesley와 harry는 같은 주소값을 가지고 있다.
snape는 new를 통해 heap영역에 새로운 주소값을 가지는 객체를 생성했다.
그렇기 때문에 wesley == harry 는 true 이지만
wesley == snape, harry == snape 는 false가 되는것입니다.
우리는 여기서 한가지 의문을 가질 수 있습니다.
그럼 문자열이 똑같은지 비교를 하는 방법은 어떻게 하나요? 주소값을 비교하지 않고 문자 생김새만 바꾸고싶습니다
라는 의문 말입니다.
해당 방법은 .equals를 사용하면 가볍게 해결할 수 있습니다.
equals의 형태는
A.equals(B) 의 형태를 가지고 있습니다. 여기서 A와 B는 비교할 대상입니다. A의 형태가 B의 형태와 같냐? 라는 의미를 가지고있습니다. 결과값은 boolean타입으로 나타납니다.
if문을 통해 알아보도록 합니다.
String wesley = "tistory";
String harry = "tistory";
String snape = new String("tistory");
if(wesley.equals(harry)) {
System.out.println("wesley와 harry의 문자 형태는 같습니다.");
}
if(wesley.equals(snape)) {
System.out.println("wesley와 snape의 문자 형태는 같습니다.");
}
if(harry.equals(snape)) {
System.out.println("harry와 snape의 문자 형태는 같습니다.");
}
변수 선언은 앞선 형태와 같고, if문의 조건문과 출력문만 바꿔주었습니다.
해당 코드의 실행 결과입니다.
결과값을 보면 알 수 있듯이 주소값이 아닌 문자열을 비교하여 모든 if문의 조건문이 true가 나오게 됩니다.
이런식으로 문자열을 비교하고 싶을 경우 equals를 잊지말고 사용하도록 합시다.
유용하게 써먹을 곳이 있을것입니다.
지금까지 참조타입에 대해서만 이야기를 했는데, 기본타입 또한 이야기해보도록 하겠습니다.
기본타입은 단순합니다. stack 영역에서 직접 저장이 되기 때문에
==을 사용해도 모두 같다고 나옵니다.
int wesley = 1;
int harry = 1;
int snape = new Integer(1);
if(wesley == harry) {
System.out.println("wesley == harry");
}
if(wesley == snape) {
System.out.println("wesley == snape");
}
if(harry == snape) {
System.out.println("harry == snape");
}
해당 코드의 결과값입니다.
모두 알맞게 나오는 것을 알 수 있습니다.
'IT Program > Java Basic' 카테고리의 다른 글
자바 메모리 관리 스택(stack) & 힙(heap) 영역 설명, 예시 (6) | 2022.03.02 |
---|---|
자바 배열(array) & 배열 출력 & 배열 for문 & 배열.length & 배열 에러 (0) | 2022.03.02 |
자바(java) 반복문 (do-while) & Scanner 예제 & 자바 문자열 받아오기 & 문자열 비교 (0) | 2022.03.01 |
자바(java) 반복문(while) & 자바 키코드(keyCode) 정리 & 키보드 제어 & while문 키보드 (0) | 2022.03.01 |
자바(java) 반복문(for문) & 구구단 출력하기 (0) | 2022.03.01 |