Hyebin‘s blog
article thumbnail
Published 2023. 1. 15. 03:32
참조 타입, 문자열 JAVA

자바의 데이터 타입은 기본타입과 참조타입 두 종류로 나뉜다. 

기본타입은 다시 정수타입(byte, char, short, int, logn) 실수타입(float, double) 논리타입(boolean) 으로 나뉜다. 

참조타입에는 배열, 열거타입, 클래스, 인터페이스가 있다. 

 

참조 타입 

참조타입이란 객체의 번지(메모리의 위치)를 참조하는 타입으로 배열, 열거, 클래스, 인터페이스 타입이 있다. 

 

객체란?

데이터와 메소드(실행 블록을 가지고 있으면서 호출에 의해서 실행이 되는 프로그래밍 요소)로 구성된 덩어리라고 생각하면 된다. 

 

기본 타입과 참조 타입의 차이점

기본타입으로 선언된 변수와 참조 타입으로 선언된 변수의 차이점은 저장되는 값이다.

변수란 ? 하나의 값을 저장하는 메모리 번지를 참조하는 이름

 

변수의 직접 값이 있는 것은 기본타입이고 변수의 번지가 있는 것을 참조타입이라고 한다.

변수를 참조한다는 것은 번지로 가서 무엇을 해라! 라고 하는것을 말한다. 실제 번지에는 객체가 있다. 따라서 객체에 있는 번지를 참조한다고 할 수 있다. 

 

//기본 타입 변수 (값을 직접 저장)
int age = 25;
double price = 100.5;

//참조 타입 변수 (String 타입은 참조타입, 직접 값을 가진 것이 아니라 참조하는 것)
String name = '신용권'
String hobby = '독서'

 변수들은 스택이라는 메모리 영역에 생성된다. 

기본 타입 변수는 직접 값을 저장하고 있지만, 참조 타입 변수는 힙 메모리 영역의 String 객체 번지를 저장하고 이 번지를 통해서 String 객체를 참조한다. 

 

 

 

메모리 영역

메모리는 램이라고 한다. 우리는 메모리를 나눠서 사용한다. 그 영역에는 메소드 영역, 힙 영역, 스택 영역으로 나눠진다.

- 메소드 영역

자바 코드가 저장되는 영역. (byte 코드)

- 힙 영역

객체가 저장되는 영역 

- 스택 영역

변수가 생성되는 영역

 

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

==, != 연산은 변수의 값이 같은지 아닌지를 조사한다.

참조 타입의 변수의 값은 객체의 번지이므로 번지를 비교하는 것이 된다.

번지가 같다면 동일한 객체를 참조하는 것이고, 다르다면 다른 객체를 참조하는 것이다.

int [] arr1; //배열 변수 선언(번지를 가지고 있는 참조 타입)
int [] arr2; 
int [] arr3; 

arr1 = new int[] {1,2,3}; //배열을 힙에 생성하고 , 힙에 생성된 번지를 저장
arr2 = new int[] {1,2,3};
arr3 = arr2;

//arr1 == arr2; 번지를 비교하는것 이므로 false 가 나온다. (참조하는 객체가 다르다.)
//arr2 == arr3; 번지가 같으므로 true가 나온다. (참조하는 객체가 같다.)

 

String str = "abc"

abc라는 문자열이 힙영역에 만들어 진다.

str 변수는 스택 영역에서 생성되면서 10번지를 참조하고 10번지를 저장한다. 

 

null과 NullPointerException

참조 타입 변수는 아직 번지를 저장하고 있지 않다는 뜻이므로 Null 값을 가질 수 있다. (기본타입은 Null을 넣을 수 없다.)

null도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 생성된다. 

이때 null은 아직까지 번지가 없는 상태이다. 

 

참조 변수가 null을 가지고 있을 경우에 이 변수를 사용할 수 있지 않다.

참조 변수는 참조 하고 있는 객체를 이용하는데, 객체가 없는 상태에서 이용한다면 문제가 생긴다.

예외상황 1 )

int[] intArray = null;
intArray[0] = 10; //NullPointerException

현재 intArray라는 변수는 배열을 참조하고 있지 않다.

그 상태에서 배열 객체 안에 0인덱스 위치에 10을 저장해라 라는 의미인데, 이럴 경우 NullPointerExcption이라는 예외가 발생한다.

따라서 위와같은 예외가 나올 경우 참조변수에 객체의 번지를 저장, 대입을 해야한다.

 

예외상황2)

String str = null; //String은 참조 타입으로 null 대입 가능, 현재 객체를 참조하고 있지 않음
System.out.println("총 문자 수 : " + str.length()); //NullPointerException
//str.length() -> 문자의 수를 나타냄

str.length() 라는 것은 str이 참조하고 있는 객체가 가지고 있는 메소드를 호출해라 라는 뜻이다.

즉, length는 객체가 가지고 있는 요소이다. 하지만 str는 객체를 참조하고 있지 않기 때문에 (즉, 객체의 번지를 가지고 있지 않기 때문) 예외가 발생한다. 

 

앞으로 NullPointerException이 발생하면 예외가 발생된 곳에서 null인 상태의 참조 변수가 사용되고 있음을 알아야한다. 

이것을 해결하려면 참조 변수가 객체를 정확히 참조하도록 변수를 대입해야한다. 

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

경우에 따라서는 참조 타입 변수에 일부러 null을 대입하기도 한다. 프로그램에서 객체를 사용하려면 해당 객체를 참조하는 변수를 이용해야하는데, 변수에 null을 대입하면 번지를 잃게 되므로 더이상 객체를 사용할 수 없게 된다. 

 어떤 변수에서도 객체를 참조하지 않으면 해당 객체는 사용할 수 없는 객체가 된다. 즉, 힙 메모리에는 있지만 위치정보를 모르기 때문에 사용할 수 없게 된다. 자바는 이러한 객체를 쓰레기로 취급하고 쓰레기 수집기(가비지 컬렉터 -> 자바 가상머신 JVM의 부가기능이다. ) 를 실행시켜 자동으로 제거한다.

자바는 객체를 직접 제거하는 방법을 제공하지 않기 때문에 객체를 제거하는 유일한 방법은 객체의 모든 참조를 없애고 가비지 컬렉터를 실행시켜 제거하는 것이다. 

String hobby = "여행"
hobby = "영화"

위 코드에서 "여행"에 해당하는 String 객체는 쓰레기가 된다. hobby 변수에 "영화"가 대입되면서 다른 String 객체의 번지가 대입되어 이전 번지를 잃어버렸기 때문이다. 

 

문자열 타입

String name; //String 타입 변수에 name 선언
name = "홍길동"; //name 변수에 문자열 대입
String hobby = "여행"; //String 타입 변수 hobby를 선언하고 문자열 대입

위 그림은 메모리를 나타낸 것이다. 변수는 스택영역에 변수가 만들어 지고 힙영역에 스트링 객체가 만들어 진다. 

객체의 번지가 변수의 값으로 들어간다. 

 

문자열 비교

String name1 = "홍길동";
String name2 = "홍길동";

자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 설계되어있다. 위 와 같이 각각의 변수의 같은 "홍길동"을 대입할 경우 동일한 String 객체의 번지가 저장된다. 

 

String name1 = new String("홍길동");
String name2 = new String("홍길동");

위와 같이 String 변수에 문자열을 new연산자로 직접 String 객체를 생성하고 대입할 수 있다. 

new 연산자는 새로운 객체를 만드는 연산자로 객체 생성 연산자라고 한다. 

이 경우  두 객체가 만들어 진다. 

 

문자열은 객체가 비록 다르다 할 지라도 그 안에 문자열이 같은지 다른지를 비교해야한다.

따라서 ==가 아닌, equals() 메소드를 사용한다. 

boolean result = str1.equals(str2); // 문자열이 같은지 검사 (대소문자 구분)
//str은 원래문자열, str2는 비교 문자열

boolean result =! str1.equals(str2);  //문자열이 다른지 검사

 

문자 추출

문자열에서 특정 위치의 문자를 얻고 싶으면 charAt()메소드를 이용할 수 있다. 

chatAt() 메소드는 매개값으로 주어진 인덱스의 문자를 리턴한다. 여기서 인덱스는 0부터 문자열의 길이-1 까지의 번호를 말한다. 

Stirng subject = "자바 프로그래밍";
Char charValue = subject.chatAt(3); //프

 

문자열 길이

문자열에서 문자의 개수를 얻고 싶다면 length() 메소드를 사용한다.

String subject = "자바 프로그래밍";
int length = subject.length(); //8

 

문자열 대체

문자열에서 특정 문자열을 다른 문자열로 대체하고 싶으면 replace() 메소드를 사용한다.

자바에서의 문자열은 불변이다.

따라서 원본 스트링을 바꿀 수 없으므로 새로운 문자열 객체를 만들어서 대입을 해줘야한다. 

String oldStr = "자바 프로그래밍";
String newStr = subject.replace("자바","JAVA");

 

문자열 잘라내기

문자열에서 특정 위치의 문자열을 잘라내어 가져오고 싶다면 substring() 메소드를 사용한다.

String ssn = "880815-1234567";
String firstNum = ssn.substring(0,6); //0에서 6앞까지, 880815
String secondNum = ssn.substring(7); //7번부터 끝까지, 1234567

 

문자열 찾기

문자열에서 특정 문자열의 위치를 찾고자 할 때에는 IndexOf() 메소드를 사용한다.

문자열이 없으면 -1을 리턴하고, 주어진 문자열이 있으면 문자열이 시작되는 인덱스트를 리턴한다. 

String subject = "자바 프로그래밍";
int index = subect.indexOf("프로그래밍"); //3

문자열이 단순히 포함되어 있는지만 조사하고 싶으면 contains()메소드를 사용하면 편리하다. 

원하는 문자열이 포함되어 있으면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

boolean result = subject.contains("프로그래밍");

 

문자열 분리

문자열을 구분자를 사용하여 여러 개의 문자열로 구성되어 있을 경우, 이를 따로 분리해서 얻고 싶다면 split()메소드를 사용한다.

String board = "번호,제목,내용,글쓴이";
String[] arr = board.split(","); //["번호","제목","내용","글쓴이"]

 

참고자료 : [자바 기초 강의] 이것이 자바다(개정판) 유튜브

 

'JAVA' 카테고리의 다른 글

열거(Enum) 타입  (0) 2023.01.15
배열  (0) 2023.01.15
switch문  (0) 2023.01.07
비교 연산자  (0) 2023.01.05
증감연산자, 오버플로우와 언더플로우  (0) 2022.12.18
profile

Hyebin‘s blog

@hyebin Lee

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그