5. 참조타입

5.1 데이터 타입 분류

자바의 데이터타입은 기본과 참조가 있다.
참조타입이란 객체의 번지를 참조하는 타입으로 배열 열거 클래스 인터페이스 타입이 있다.
객체부분은 가장중요한부분이니 개념을 정확히 이해하기 왜 이코드가 이 의미를 가지느지 알기.
참조타입 자체를 이해할 필요가 있다. 참조타입이란 객체의 번지를 참조하는 타입이다.

여기서 잠깐 객체란? 객체는 데이터와 메소드로 구성된 덩어리 객체 = 데이터(필드)+메소드
메소드는 실행블록을 가지고 있으면서 호출로 불러짐.
기본타입과 참조타입의 차이점은 저장되는 값이다.
기본타입은 선언된 변수는 값 자체를 저장하고 있음.
참조타입으로 선언된 변수는 객체가 생성된 메모리 번지를 저장한다.

String = 참조타입 변수임. 직접 갑을 가지고 있지 않음.
String name = "신용권" 일때 name이 신용권을 직접 가지고 있는게아님.

변수들은 스택이라는 메모리 영역에 생성된다. 참조타입 변수는 힙 메모리 영역의 String 객체 번지를 저장하고 이 번지를 통해 String 객체를 참조한다.


5.2 메모리 사용영역

https://st-lab.tistory.com/198 메모리 구조 참조

메소드 영역 바이트코드 파일을 읽은 내용이 저장되는 여역 클래스별로 상수 정적필드 메소드코드 생성자 코드등이 저장
단순히 바이트코드파일의 내용이 저장되는 영역
힙영역 힙영역은 객체가 생성되는 영역 객체의 번지는 메소드영역과 스택영역의 상수와 변수에서 참조할수 잇다.
스택영역 스택영역은 메소드를 호출할때마다 생성되는 프레임이 저장되는 영역 메소드 호출이 끝나면 프레임은 자동제거된다.
프레임 내부에는 로컬변수스택이 있다. 여기에서 기본타입변수와 참조타입변수가 생성되고 제거된다.

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

참조타입 변수는 객체의 번지이므로 참조타입변수의 == !=연산자는 번지를 비교하는 것이다.
번지가 같다면 동일한 객체를 참조하는거 다르다면 다른 객체를 참조하는것

int [] arr1; //배열변수 arr1선언
int [] arr2; //배열변수 arr2선언
int [] arr3; //배열변수 arr3선언

arr1 = new int[] {1, 2, 3}; //배열 {1,2,3}을 생성하고 arr1변수에 대입
arr2 = new int[] {1, 2, 3}; //배열 {1,2,3}을 생성하고 arr2변수에 대입
arr3 = arr2;

System.out.println(arr1 == arr2); //->false
System.out.println(arr2 == arr3); //->true
//arr1과 arr2의 저장항목은 같지만 서로 다른 배열 객체로 생성되므로 arr1과 arr2 변수에 대입되는 번지가 다르다.
//arr3은 arr2의 번지가 대입되었기 때문에 두 변수는 동일한 번지를 가지며 같은 배열을 참조한다.

5.4 Null과 NullPointerException

String refVa1 = "자바"; ->힙영역 String refVar2 = null; -> 스택영역에 생성
null상태의 객체의 데이터나 메소드를 사용하려하면 오류(예외)가 발생한다. 가장많이 발생하는 오류가 NullPointerException이다.

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

String str = null;
System.out.println("총 문자 수: " + str.length() );//NullPointerException 발생

변수에 null을 일부러 대입하면 번지를 잃게 되므로 더이상 객체를 사용할 수 없게된다.
힙 메모리에는 있지만 주소를 잃어버려 사용할수 없게됨.
자바는 이런 객체를 '쓰레기'로 인식하고 '쓰레기 수집가'를 실행시켜 자동으로 제거한다.
자바는 객체를 직접 제거하는 방법을 제거하지 않는다 . 객체를 제거하는 유일한 방법은 모든 참조를 없애는 것임.

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

String kind1 = "자동차";
String kind2 = kind1;
kind1 = null; //kind1을 삭제해도 kind2가 그 주소를 참조하고 있기 때문에 자동차를 가진 String객체는 쓰레기 객체가 아니다.

System.out.println("kind2: " + kind2); //kind2: 자동차

5.5 문자열(String)타입

자바의 문자열은 String 객체로 생성된다. 문자열 리터럴이 대입되면 문자열은 String객체로 생성되고 객체의 번지가 각각 대입된다.

String name;
name = "홍길동";
String hobby = "여행";

문자열비교
문자열 리터럴이 동일하다면 String객체를 공유하도록 설계되어 있다.

String name1 = "홍길동"; // 주소10번지
String name2 = "홍길동"; // 주소10번지

String 변수에 문자열 리터럴을 대입하는게 일반적이지만 new 연산자로 직접 String 객ㅊ체를 생서하고 대입할 수도 있다.
new연산자는 새로운 객체를 만드는 연산자로 객체 생성 연산자라고 한다.
문자열 리터럴과 new연산자로 생성하느냐에 따라 비교연산의 결고가 달라질수 있다.

String name1 = new String("홍길동"); // 주소10번지
String name2 = new String("홍길동"); // 주소 20번지

내부 문자열만 비교할 경우에는 equals()메소드를 사용한다.

boolean result = str1.equals(str2);
boolean result != str1.equals(str2);

String strVar1 = "홍길동";
String strVar2 = "홍길동";

if (strVar1 == strVar2)
{
    System.out.println("strVar1과 strVar2는 참조가 같음");
}
else
{
    System.out.println("strVar1과 strVar2는 참조가 다름");
}

if(strVar1.equals(strVar2))
{
    System.out.println("strVar1과 strVar2는 문자열이 같음");
}

String strVar3 = new String("홍길동");
String strVar4 = new String("홍길동");

if (strVar3 == strVar4)
{
    System.out.println("strVar3과 strVar4는 참조가 같음");
}
else
{
    System.out.println("strVar3과 strVar4는 참조가 다름");
}
if(strVar3.equals(strVar4))        
{
    System.out.println("strVar3과 strVar4는 문자열이 같음");
}

5.5.1 문자추출

문자열에서 특정 위치의 문자를 얻고 싶다면 charAt() 메소드를 이용할 수 있다.
charAt() 메소드는 매개값으로 주어진 인덱스의 문자를 리턴한다. 여기서 인덱스란 0에서부터 문자열의 길이-1까지의 번호를 말한다.
String subject = "자바 프로그래밍";
char charValue = subject.charAt(3);
자바 프로그래밍 01234567(0부터 시작, 띄어쓰기포함) -> 프

String ssn = "9506241230123";
char sex = ssn.charAt(6);
switch (sex)
{
    case '1':
    case '3':
        System.out.println("남자입니다.");
        break;
    case '2':
    case '4':
        System.out.println("여자입니다.");
        break;
}

5.5.2 문자열의 길이

문자열에서 문자의 개수를 얻고싶다면 length()메소드를 사용한다.
String subject = "자바 프로그래밍";
int length = subject.length();
자바 프로그래밍 01234567 총 8문자;

String ssn = "9506241230123";
int length = ssn.length();
if(length == 13)
{
    System.out.println("주민등록번호 자릿수가 맞습니다.");
}
else
{
    System.out.println("주민등록번호 자릿수가 틀립니다.");
}

5.5.3 문자열대체

특정 문자열을 다른 문자열로 대체하고 싶다면 replace() 메소드를 사용
기존문자열을 그대로두고 대체한 새로운 문자열을 리턴한다.
String oldStr = "자바 프로그래밍";
String newStr = oldStr.replace("자바", "JAVA");
자바 프로그래밍 -> JAVA 프로그래밍

String oldStr = "자바 문자열은 불변입니다. 자바 문자열은 String입니다.";
String newStr = oldStr.replace("자바", "JAVA");

System.out.println(oldStr);
System.out.println(newStr);

5.5.4 문자열 찾기

특정문자열의 위치를 찾고자할때는 indexOf()메소드를 사용한다.
indexOf()메소드는 주어진 문자열이 시작되는 인덱스를 리턴한다.
String subject = "자바 프로그래밍";
int index = subject.indexOf("프로그래밍");
자바 프로그래밍 01234567 3번부터 시작해서 3을 출력한다.
포함되어 있지 않으면 -1을 리턴한다. if(index == -1) 은 포함되어있지않으면 이라는 뜻이다.
단순히 포함되어있는지만 조사하고 싶다면 contains() 메소드를 사용하면 편리하다. 원하는 문자열이 포함되어있으면 contains()메소드는 true 아니면 false
boolean result = subject.contains("프로그래밍")

String subject = "자바 프로그래밍";

int location = subject.indexOf("프로그래밍");
System.out.println(location); //3
String substring = subject.substring(location); 
System.out.println(substring); //프로그래밍

location = subject.indexOf("자바");
if (location != -1)
{
    System.out.println("자바와 관련된 책이군요.");
}
else
{
    System.out.println("자바와 관련 없는 책이군요."); //자바와 관련된 책이군요.
}

boolean result = subject.contains("자바");
if (result)
{
    System.out.println("자바와 관련된 책이군요.");
}
else
{
    System.out.println("자바와 관련 없는 책이군요."); //자바와 관련된 책이군요.
}

5.5.5 문자열 분리

문자열이 구분자를 사용하여 여러개의 문자열로 구성되어 있을경우 이를 따로 분리해서얻고 싶다면 split()메소드를 사용한다.
String board = "번호, 제목, 내용, 글쓴이";
String[] arr = board.split(",");
board는 ,로 구분된 문자열을 가지고 있다.
split()메소드를 호출할때 ,를 제공하면 분리된 문자열로 구성된 배열array를 얻을 수 있다.
arr[0] "번호" arr[1] "제목" arr[2] "내용" arr[3] "글쓴이"

String board = "1, 자바 학습, 참조 타입 String을 학습합니다., 홍길동";

//문자열 분리
String[] tokens = board.split(",");

//인덱스별로 읽기
System.out.println("번호: " + tokens[0]);
System.out.println("제목: " + tokens[1]);
System.out.println("내용: " + tokens[2]);
System.out.println("성명: " + tokens[3]);
System.out.println();

//for문을 통해 읽기
for (int i = 0 ; i < 4; i++ )
{
    System.out.println(tokens[i]);
}

문자열 정리

char 변수이름2 = 변수이름1.charAt() int 변수이름2 = 변수이름1.length() String 변수이름2 = 변수이름1.replace()
int 변수이름2 = 변수이름1.indexOf("찾을 문자리터럴") = 문자시작점번호; String[] 변수이름2 = 변수이름1.split("나눌기준");

'기초단계 > JAVA' 카테고리의 다른 글

2022.11.16-3 JAVA 참조타입 3  (0) 2022.11.16
2022.11.16-2 JAVA 참조타입 2  (0) 2022.11.16
2022.11.15-3 JAVA 반복문  (0) 2022.11.15
2022.11.15-2 JAVA 조건문  (0) 2022.11.15
2022.11.15-1 JAVA 연산자  (0) 2022.11.15

+ Recent posts