자바 7. 클래스? 객체? 인스턴스? 그리고 배열과 String

Bluewiz_YSH·2022년 7월 6일
0

1. 클래스와 객체, 인스턴스

우리가 자바 4장 클래스를 만드는 형식과 메소드 그리고 생성자 부분에서 간단히 보았지만 클래스는 1개 이상의 멤버 변수 혹은 1개 이상의 메소드가 있는 집합체인데 단순히 말해서 현실 세계로 따지만 '어떠한 것'이라고 할 수 있다.

현실에서 우리는 나 자신이라는 존재와 나를 둘러싸고 있는 다른 것들을 생물이냐 무생물이냐의 기준으로 나누자면, 살아서 나와 공존하는 다른 인간들/사람들과 동식물들

그리고 무생물로서 환경으로서 있는 존재들 (바위 산, 바다 등등) 또는 도구로서 인간들에게 유익한 이점을 주는 것들 (기계) 또는 무생물이면서도 생물로서 장애물로서 위협이 되는 것들 (바이러스)

이렇게 현실 세계는 '수많은 것들'이 '서로에게 또는 혼자' '다양한 작용'을 한다. 자바에서는 이를 프로그램 내에서 구현한 것이 바로 클래스이며 메모리에 구현되는것까지 포함하면 객체, 즉 인스턴스라고 부른다.

즉, 클래스에서 1개 이상의 멤버 변수는 '어떠한 것'들이 가지는 '특성' '요소'라고 볼수 있겠고, (이 사람은 코가 크다, 저 사람은 키가 크다 등등) 1개 이상의 메소드는 그러한 '특성' 혹은 '요소'를 어느 정도 반영해 메소드 자신이 속한 클래스의 어떤 동작, 기능(이 사람은 코가 큰 걸 이용해 냄새를 맡는다, 저 사람은 키가 큰 걸 이용해 농구를 한다)을 수행한다. 이런 클래스에 해당하면서 실제 프로그램 메모리 안에 구현되어있으면서 (현실로 따지만 현실 세상에 실존하는) 프로그래머인 내가 해당 클래스 안에서 정한거면 어떤 멤버 변수든 메소드든 규칙이든 상관없이 변수 값을 바꿔주거나 특정 메소드를 실행하면 그 내가 조율해둔 마지막 결과값을 품고 있는, 어떤 특정 사례가 바로 인스턴스다. (현실 세계에 존재하는 나의 모습, 다른 사람의 모습, 동식물의 모습)

그리고 자바는 몇번이나 말했지만 다른 언어 중에서도 상당히 객체지향적인 언어이기에 이 클래스와 객체 인스턴스는 서로 바탕이 된 클래스간 어떤 변수나 요소, 메소드 등을 공유하도록 만들어두었다면 소스 코드에 서로 주고 받도록 코드를 짠 뒤 실행하면 그대로 주고 받고 할수 있는것이다.

즉, 객체는 클래스를 실제 프로그램 메모리에 구현한 것이며 클래스는 곧 객체이자 객체의 바탕이 되는 설명서 같은것이고 그래서 클래스는 '객체'의 자료형이 될수 있으며 객체는 '주소'를 참조해야 접근할수 있기에 이를 (주소를 참조해야 한다고 해서) 클래스를 참조 자료형이라고 한다.

클래스와 객체는 서로 뗄레야 뗄수 없으며 다른 클래스와 객체 또한 미리 정해둔 코드(규칙)가 있다면 서로 주고 받는 흐름도 프로그램 내에서 구현할수 있는것이다.

그래서 우리가 클래스에 정해둔 멤버 변수와 메소드 즉, 요소와 기능을 쓰기 위해선 먼저 객체를 메모리에 올려둬야 하기 때문에 객체 생성을 해야하고 이는 생성자를 써서 객체를 만든다는 의미와 같다.

4장에서 살짝 보았지만 생성자를 이용한 객체 생성 문법은 다음과 같다:

참조 자료형 (<= 클래스명) 객체명 = new 참조 자료형 () (<= 생성자);

//이렇게 생성자를 이용해 해당 클래스의 객체를 생성한다는것은 해당 클래스의 원본을 그대로 복사해 객체가 올라가는 메모리 (Heap 메모리)에 올려둔다는 의미이다.

여기서 그 다음으로 객체명이 생기니 아래 형식처럼 접근 제어자 (.)을 이용해 해당 클래스(정확히는 객체)의 멤버 변수 혹은 메소드를 사용할수 있게 되는것이다:

객체명.멤버 변수명, 객체명.메소드명(); //해당 메인 메소드가 있는 클래스와 객체 클래스의 패키지가 만약 다르다면 패키지명까지 적어줘야 한다. 패키지명.객체명.메소드명();

이렇게 클래스와 객체를 다 따로 따로 해두는 이유는 코드의 간편성 편의성은 물론 객체지향적인 특성에 따라 클래스간 객체간 흐름이 원할하도록 만드는데 의의가 있다.

2. 배열

배열은 같은 자료형의 여러개 값들을 한번에 저장하고 있는 집합체(객체)이다. 예를 들자면 고등학교에는 1학년, 2학년, 3학년 학생들이 있는데 이들은 공통되는 요소로 각각 같은 1학년/2학년/3학년이라는 자료형을 띄면서 모두 학생인 사람들을 뜻한다.

자바 또한 마찬가지이다. 백엔드에서 데이터를 다루는 자바 특성상 같은 자료형의 데이터들을 한꺼번에 저장하고 수정하고 해야하는 상황이 많은데 배열은 이런 상황에서 자료를 쉽게 다루도록 만들어준다.

일단 배열을 만드는 형식은 다음과 같다:

1번 유형 => ① 선언 먼저 하고 ② 그 다음 공간 할당, ③ 마지막으로 초기화 :
① (참조)자료형 [] 변수명/객체명; // (참조)자료형 변수명/객체명 [];도 동일하다.
② 변수명/객체명 = new 자료형 [저장 공간 개수];
③ 변수명/객체명 [해당 공간 인덱스 번호] = 리터럴(상수, 흔히 말하는 숫자값)/객체명;

2번 유형 => ① 선언과 공간 할당 동시에, ② 그 다음 초기화 :
① (참조)자료형 [] 변수명/객체명 = new (참조)자료형 [공간 개수];
② 변수명/객체명 [해당 공간 인덱스 번호] = 리터럴/객체명;

3번 유형 => ① 선언과 공간 할당 그리고 초기화까지 한꺼번에 :
① (참조)자료형 [] 변수명/객체명 = new 자료형 [] {값1, 값2, 값3 ... 값n};

4번 유형 => 3번 유형의 단축 형식 :
(참조) 자료형 [] 변수명 = {값1, 값2,....값n};
// 단, 오른쪽 값들로 충분히 자바에서 어떤 자료형인지 인식할수 있는 경우에 한 함. (기본 자료형)

※ 인덱스 번호는 각 저장 공간의 순서 번호를 가리키며 첫번째 공간의 인덱스 번호는 0이다.

그럼 아래 예제를 한번 입력해보고 실행해보자.

int[]a; //int a[];

a = new int[]{1,2,3,4,5};

System.out.println(a);

for(int i = 0; i < 5; i++)

System.out.print(a[i] + " ");

System.out.println();

System.out.println(a.length);

분석해보자면 a라는 변수를 int 자료형을 기본으로 배열 선언하면서 첫번째 줄을 시작했으며 여기에 new int []{값1, 값2,...값n} 유형으로 공간 할당과 각각의 공간의 값을 초기화 한것이 두번째 줄이며 이를 콘솔에 일단 출력한것이 세번째 줄까지이다.

그런 뒤 for문을 돌려 a[i]가 a[0]번부터 a[5]번이 될때까지 콘솔에 한줄 안에 반복 출력하도록 만든 뒤 다음줄로 한줄 뛰어서 마지막 배열 공간 전체의 길이를 나타내는 코드인 변수명/객체명.length, 여기서는 a.length를 출력문 매개 변수에 넣어 콘솔에 a 배열의 길이가 출력되게끔 해놓았다.

이런 결과가 아래 사진과 같이 나온다.

맨 위의 알수 없는, 이상한 문자와 숫자로 랜덤하게 나온 결과값은 바로 이 배열의 주소, 즉 프로그램 메모리 위에 올려져있는 실제 배열을 가리키는 주소를 뜻한다. 이처럼 배열이든 다른 객체 자료형이든 객체를 출력문 매개변수에 그냥 넣어서 실행하면 이렇게 콘솔에서는 실제 값 자체가 아니라 주소를 표시한다. (이 주소는 나중에 보겠지만 해쉬코드 HashCode라고 한다.)

그리고 두번째 줄에는 배열 공간 순서대로 각각 저장된 값이 1부터 5까지 차례대로 잘 있음을 나타내고 있으며 마지막 세번째 줄은 1부터 5까지 저장된 공간의 갯수인 5를 정확히 표시하고 있다.

이번에는 for문의 다른 버젼인 향상된 for문(for 단축문)과 배열의 조합을 예시로 보겠다.

int [] c = {1,2,3,4,5};
		
for(int i : c) // for 콜로문 for 단축문 향상된 for문 : 뒤에 오는 값이 배열이상 급 반복할수 있는 값인 경우
//for(객체의 기본 자료형 변수명 : (배열) 객체명){실행문;} 배열 객체 인덱스 순서대로 1개씩 떼옴

System.out.print(i + " "); //for문의 실행문
System.out.println();

일단 int 자료형으로 배열 c가 1부터 5까지 차례대로 5개의 값을 받는 단축 코드문이 있고

그리고 이 배열 c 전체가 다음줄 for 단축문인 for(int i : c)에 넣어져

for문 안에선 i로 대입되어 인덱스 0번부터 4번까지 각각 한번씩 for문 아래

실행문 System.out.print(i + " ");을 거쳐

한줄 안에 배열 전체가 인덱스 번호 순서대로 출력되도록 코드가 짜여져있다.

즉, 위의 예시와 별반 다르지는 않지만 코드를 단축해서 훨씬 더 보기 편하게 하고 싶다면

이렇게 배열을 만드는 코드문도 for문도 단축해서 쓸수 있는것이다.

그럼 다른 몇가지 예제들을 쭉 보면서 배열에 익숙해져보자.(설명은 // 주석에 다 적어놓았다.)

int[] b = new int[5]; //배열은 생성하자마자 자료형에 맞춰 자동 초기화값 부여

b[2] = 1; //배열 b의 2번 인덱스에 1 대입,그 이외의 다른 배열의 값은 0

System.out.println(b); //배열이 위치한 주소값 해시코드 출력 (배열 자체 값 x)

for(int i = 0; i < b.length; i++) //for 반복문 + b.length 배열 전체 길이 => 반복 횟수
	System.out.print(b[i] + " "); // 배열의 실행문 단 하나, 한줄 안에 배열 모든 값 출력
	System.out.println();

int[] a = new int[5]; //배열 선언 및 공간 할당

int i;

a[0] = 50; 
a[1] = 100;
a[2] = 150;
a[3] = 200;
a[4] = 250; // 인덱스 0번부터 4번까지 5개 각각 값 대입

for (i = 0; i < a.length; i++) //for 반복문 + a.length 배열 전체 길이 => 반복 횟수
	System.out.println("a[" + i + "]= " + a[i]); //배열 이름[해당 인덱스 번호]= 배열 각각 해당 인덱스 번호에 맞는 값 출력

int[] score =
		{ 79, 88, 91, 33, 100, 55, 95 }; /여러개의 int 자료형 값 배열로 바로 대입 (단축형)

		int max = score[0]; //일단 최대값 저장될 변수에 score[0] 값으로 초기화
		int min = score[0]; //일단 최소값 저장될 변수에 score[0] 값으로 초기화

		for (int i = 1; i < score.length; i++) //score.length 배열 전체의 길이
		{
			if (score[i] > max) //배열에 존재하는 값들 중 최대값을 가려내기 위한 연산
				max = score[i]; 
			if (score[i] < min) //배열에 존재하는 값들 중 최소값을 가려내기 위한 연산
				min = score[i];
		} //max min 값 정하기 위해 for문으로 한번씩 돌려보면서 비교 대입 연산

System.out.println("최대값 : " + max); //최대값 출력
System.out.println("최소값 : " + min); //최소값 출력

+) 임포트문 import java.util.Arrays와 Arrays.toString(배열 이름)을 이용하면

고스란히 배열 모양으로 배열 객체를 반환받을수 있다.

int [] array = new int[] {3,4,5,6,7};
		
for(int k : array) {
	System.out.print(k + " ");
	}
	System.out.println();
	// Arrays 이용
System.out.println(Arrays.toString(array)); //Arrays.toString 메서드 => [] 대괄호 붙이고 배열 반환

++) 또한 System 객체의 arraycopy 메서드를 이용하면 배열의 특정 값을 복사해 다른 배열의 특정 위치부터 붙여넣기 할수 있다.

		int [] old = {1,2,3};
		
		int [] newArr = new int [5];
		
		for(int i : old) System.out.print(i);
		System.out.println();
		
		System.arraycopy(old, 0, newArr, 2, 2); // 배열 특정 구간 복사 
		// (원본 배열 객체명, 시작할 인덱스 번호 위치, 복사해서 넣어놓을 배열 객체명(공간 할당이 미리 되어있어야 함), 복사값 넣을 시작 위치, 객체 값 가져올 개수)
		for(int i : newArr) System.out.print(i);

System.arraycopy(old, 0, newarr, 2, 2)

=> System.arraycopy(복사할 오리지널 배열 이름, 인덱스 번호 기준 복사할 값 시작 위치, 붙여넣기할 복사본 배열 이름, 인덱스 번호 기준 붙여넣기 받을 공간 시작 위치, 복사할 값 갯수)

그래서 결과는 아래 사진처럼 나온다.

(위 123 => 오리지널 배열 old 전체 각각 값

아래 00120 => 복사본 배열 new arr 전체 각각 값)

그리고 이제 한단계 업그레이드해서 다음에 볼 내용은 배열이 두개로 이뤄진 2차원 배열이다.

원래 배열은 다차원으로 쌓을수 있긴한데 2차원 배열을 많이 쓰기에 2차원 배열을 보겠다.

2차원 배열은 수리 시간에 배웠던 행렬과 같은 구조로 되어 있으며,

다른건 1차원 배열과 같지만 [] 대괄호가 하나 더 들어간다:

자료형 [가로줄 수 = 행][세로줄 수 = 열] 배열명, new 자료형 [행][열]

아래 예시를 보겠다.

int[][] a = new int[2][3]; //[행][열] 2차원 배열
	
a[0][0] = 0;
a[0][1] = 1;
a[0][2] = 2;
a[1][0] = 3;
a[1][1] = 4;
a[1][2] = 5;

for(int i = 0; i < a.length; i++) { 

//2차원 배열명.length  = '행의 개수' 2차원 배열은 무조건 처음으로는 행이 기준! length도 같음!

	for (int j =0; j < a[i].length; j++) {

		if(j == a[i].length - 1) 

//2차원 배열명[해당 행번호].length  = '해당 행'의 '열의 개수'

//여기에 1을 빼는건 마지막 인덱스 번호를 가리킨다.

System.out.println(a[i][j]); 

// 열 마지막 번호 == 해당 행의 열의 개수 - 1 => 해당 행의 열의 마지막 번호 차례

else
	
    System.out.print(a[i][j] + " "); }

}

일단 위 예시에서는 new int[2][3]에서 보다시피 가로 2개 길이, 세로 3개 길이의 2차원 배열을

만들었다 즉, 행은 2행에 열은 3열인 총 6개 공간을 가진 2차원 배열로 만들었다는것이다.

그리고 a[행 인덱스 번호][열 인덱스 번호]에 따라 각각 값을 대입해주었고

(당연히 인덱스 번호는 0번부터이다.)

이걸 for 중첩문으로 돌리되, 바깥 for문은 int i를 기준으로 i < a.length이므로

(a.length 값은 행 개수, 2차원 배열은 무조건 행이 우선된다고 보면 된다)

i는 행 갯수를 대표하고 그 안쪽 for문 j는 j < a'[i]'.length이므로

(a[i].length 값은 인덱스 번호 i행에 해당하는 열의 개수이다)

j는 열 갯수를 대표한다고 보면 된다.

여기서 if(j == a[i].length - 1)는 j가 어떤 행의 마지막 열 번호와 동일할때를 의미하므로

그 뒤에 따라오는 System.out.println(a[i][j]);과

else문의 System.out.print(a[i][j] + " ");을 보면

행마다 마지막 인덱스 번호에 해당하는 값만 뒤에 공백이 없고 (당연히 마지막 순서 값이니까)

나머지는 공백이 뒤에 있기 출력하는것으로 나뉜다는것을 알 수 있을것이다.

그리하여 결과는 아래 사진과 같다.

(2차원 배열 모습 그대로와 출력한것이 동일하다)

아래 2차원 배열을 생성하는 예시들도 한번 보면 [] 대괄호 하나 더 붙은것과 배열이름.length가

행과 열 중 행 갯수를 의미한다는것 빼고는 나머지 처리 방식은 똑같다:

int[][] a = new int[2][]; //일단 2줄 배열 크게 만듬
		
	a[0] = new int [2]; // 첫번째 줄 안에 2칸짜리 공간을 만듬
	a[1] = new int [3]; // 두번째 줄 안에 3칸짜리 공간을 만듬
        
int[][] b = {{0,1},{2,3,4}}; //선언, 공간할당, 초기화 한번에 동시에 단축형식   

3. String 문자열

String은 우리가 앞서 살짝 본것과 같이 공백, 빈 문자열 포함 하나 이상의 문자 및 문장을 저장하는 유일무이한 '객체'로 보면 된다. (그래서 당연히 String 객체명이 가진것은 실제 String 객체 자체 값을 가리키는 주소만을 가진다)

(실제로 자바 내 기본 패키지에 String '클래스'가 있다.)

말보다 아래 예시를 보는게 더 빠를것이다:

String s1 = "Java Korea"; // String 객체 자체값은 static 영역 상수풀에 유일무이로 저장됨
		// 직접 문자열을 지정(canonical 문자열)
		// 단축 (shorthand) 초기화로 객체 생성
		String s2 = new String("Java Korea");
		String s3 = s2.intern(); // intern 메서드는 String이 저장된 상수 풀에서 동일한 문자열이 있으면 그대로 반환 (새로 생성x) 없으면 새로 생성후 반환
		// s2 문자열을 canonical 문자열로 전환
		String s4 = "Java Korea";
		// 단축 초기화로 객체 생성 => 새로 객체 생성x
		
		System.out.println(">> String 객체가 참조하는 주소가 같은지 비교"); //힙에서는 생성된 방법에 따라서 각각 다르거나 똑같은 힙 주소가 저장됨
																 //==은 대상이 객체일 경우 똑같은 값을 가리키는지 주소값을 비교
		System.out.println("s1 == s2 : " + (s1 == s2));
		System.out.println("s2 == s3 : " + (s2 == s3));
		System.out.println("s1 == s3 : " + (s1 == s3));
		System.out.println("s1 == s4 : " + (s1 == s4));
		System.out.println();
		
		System.out.println(">> String 데이터 값(내용)이 같은지 비교"); // 데이터 값 자체!
		System.out.println(s1.equals(s2));
		System.out.println(s2.equals(s3));
		System.out.println(s1.equals(s3));
		System.out.println(s1.equals(s4));
		System.out.println();
		
		System.out.println(">> String 데이터의 해시코드: static 메모리"); // static에 올라간 유일무이 String 데이터 값 자체를 가리키는 주소! 
		System.out.println(s1.hashCode());
		System.out.println(s2.hashCode());
		System.out.println(s3.hashCode());
		System.out.println(s4.hashCode());
		
		System.out.println(">> String 데이터의 식별해시코드: heap 메모리"); // 그 유일무이 String 데이터를 가리키기 위한 객체의 생성된 방법에 따라서 똑같거나 달리 저장되는 주소!
		System.out.println(System.identityHashCode(s1));
		System.out.println(System.identityHashCode(s2));
		System.out.println(System.identityHashCode(s3));
		System.out.println(System.identityHashCode(s4));

String 자체 객체값은 우리가 앞서 살짝 배웠던 static 영역, 클래스와 메서드 및 그 메서드의 지역변수가 저장되는 메모리 영역에 상수풀로 유일무이하게 저장된다.

일단 s1부터 보면, 위의 s1 선언 및 초기화 방식은 ""안에 직접 문자열을 지정하는 canonical 문자열로 저장되었으며 선언과 초기화를 동시에 했으므로 단축 형식이다.

s2는 우리가 여태까지 봐왔던 new 키워드를 이용한 생성자로 객체 생성과 비슷하게 String 객체를 만든것으로 생성자 안에 매개변수로 준 "Java Korea"를 가지고 새로운 객체를 만든것이기에 s1과 같은 값 자체를 가졌지만 객체로 보면 엄연히 s1과 s2는 다른 객체이다.

s3는 s2 객체의 intern()메소드를 붙인 결과값을 저장한 String 객체로 intern 메소드는 같이 붙여진 String 객체 자체 값이 이미 있다면,(s1,s2) 그대로 그 값을 반환한다. (없다면 새로 생성해 반환)

s4는 이전에 만들어뒀던 "Java Korea"값을 그대로 대입 초기화 받은것에 불과하다.(s1,s3,s4는 저장한 주소가 같아 실질적으로 같은 객체를 가리킴)

그 이후 여러가지 방법으로 s1, s2, s3, s4를 비교하는 방법을 보여주는데, 첫번째는 우리가 비교 연산자에서 배웠던 ==, 동일하다 같다라는 의미를 가진 연산자를 이용했는데 이 연산자로 같음을 비교하면 객체의 주소값이 동일한지를 비교하기 때문에 s2가 들어간 비교들을 제외한 나머지 비교에서는 모두 true를 나타낸다.

두번째는 자바의 모든 클래스의 기원인 최상위 Object 클래스에서 기반했지만 String 클래스에서 재정의된, (오버라이드라고 하며 부모-자식 클래스 상속 상황에서 (Object 부모 - String 자식, Object는 기본적으로 모든 클래스의 부모 클래스이다.) String 클래스가 부모 클래스의 equals 메소드를 가져와 String 클래스의 객체만 쓸수 있는 커스텀 equals 메소드를 만든것이다. 나중에 상속과 오버라이드에 대해 자세히 기술하겠다) equals 메소드를 이용한것인데 객체1.equals(객체2)에서 객체1과 객체2의 주소값을 비교하는게 아니라 객체 자체 값이 동일할때 true, 아니라면 false를 반환한다. 이 경우에는 s1,s2,s3,s4 모두 자체 값은 "Java Korea" 동일한 값을 가지고 있기 때문에 equals 메소드 비교 결과값은 모두 true를 나타낸다.

세번째와 네번째 비교는 각각 두번째와 같이 자바 최상위 클래스 Object의 메서드 hashCode()와 identityHashCode() 메서드를 이용한 비교인데 String에서 또한 오버라이드 재정의된 메서드로써 hashCode() 메서드는 String 객체 '자체 값'을 결과 값으로 내놓고 identityHashCode() 메서드는 String 객체 '주소 값'을 결과 값으로 내놓기에 hashCode()메소드에선 s1,s2,s3,s4 모두 동일한 값을 가지지만 identityHashCode()메서드에선 아까 객체가 달리 생성됐던 s4만 제외하고 나머지 s1,s2,s3만 동일한 값을 가진다.

그리하여 그런 모든 결과값들이 콘솔에 출력된게 바로 아래 사진이다.

이제부터 String 객체에 올수 있는 메소드들에 대해 알아보겠다.

concat(): 매개변수로 받은 문자열을 해당 String 객체 뒤에 문자열로 추가한 뒤 반환

String str = new String("Java");
System.out.println(str.concat("수업")); // => Java수업 출력 

length(): 해당 String 객체를 문자로 각각 나눴을때 (공백포함) 그 문자들 총 갯수 (=String 객체의 총 길이)

String str1 = "해피썬데이"
System.out.println(str1.length()); // => 5 출력
str1 = "  " + str1 + "  " //앞 뒤 공백 2개 추가후 대입
System.out.println(str1.length()); // => 9 출력

trim(): 해당 String 객체가 앞 뒤로 공백이 있으면 그 공백들을 지우고 난 뒤 그 문자열을 반환

String str1 = "  해피썬데이  "; //(공백 2개)+해피썬데이+(공백 2개)
System.out.println(str1.trim()); // => "해피썬데이" 출력
System.out.println(str1.length()); // => 5 출력

charAt(): 해당 문자열 객체에 대해 매개변수로 주어진 특정 인덱스 번호값 순서에 해당하는 문자를 결과로 반환 => char 자료형으로 반환

String s1 = "자바 프로그래밍 입문";
char ch = s1.charAt(3);
System.out.println(ch); // => 프 출력

substring(): ① 매개변수 상수 하나만 받을때 => 그 값을 특정 인덱스 위치로 보고 그 위치부터 문자열 끝까지의 문자열 값을 반환
② 매개변수 상수 두개를 받을때 => 첫번째 매개변수는 인덱스 시작 위치 두번째는 거기서 1을 뺀 인덱스 번호가 마지막 위치 => 시작 위치를 포함하면서 시작해 1을 뺀 인덱스 번호까지 그 문자열 값을 반환

str2 = "자바 즐거워요";
System.out.println(str2.substring(3)); //"즐거워요" 출력
System.out.println(str2.substring(5, 7)); //"워요" 출력, 만약 매개변수 두개의 조합으로 해당 String 객체의 길이보다 더 긴 문자열 값을 반환해야할 경우 오류 발생 즉, 문자열의 길이를 정확히 알고 써야함!

indexOf(): ① 매개변수 String 객체 하나만 받을때 => 해당 객체열 전체에서 매개변수로 주어진 문자열이 있는지 '왼쪽'에서 '오른쪽'으로 찾고 찾으면 가장 먼저 찾은 문자열의 가장 첫 문자의 인덱스 번호를 반환

String str = "Good Afternoon";
System.out.println(a.indexOf("noon"); // <= 10 반환
System.out.pritnln(a.indexOf(" AF"); // <= 4 반환

indexOf(): ② 첫번째 매개변수 String 객체 두번째 매개변수 상수값 받을때 => 해당 객체를 '왼쪽'부터 '오른쪽'으로 보면서 찾되 '먼저 인덱스 0번부터 상수값만큼 이동하고' 그 위치부터 시작해 첫번째 매개변수로 주어진 String 객체값을 찾아 찾으면 그 첫 문자의 인덱스 번호를 반환

String hello = "HelloWorld_MyWorld";
System.out.println(hello.indexOf("World", 10)); // => 두번째 매개변수가 10이므로 _에서 시작, 거기서 왼쪽에서 오른쪽으로 찾으므로 MyWorld에서 World를 찾고 해당 첫 글자 W의 인덱스 번호가 13이므로 13 반환

lastIndexOf(): ① 매개변수 String 객체 하나만 받을때 => 해당 객체열 전체에서 매개변수로 주어진 문자열이 있는지 '오른쪽'에서 '왼쪽'으로 찾고 찾으면 가장 먼저 찾은 문자열의 가장 첫 문자의 인덱스 번호를 반환
② 첫번째 매개변수 String 객체 두번째 매개변수 상수값 받을때 => 해당 객체를 '오른쪽'부터 '왼쪽'으로 보면서 찾되 '먼저 인덱스 0번부터 상수값만큼 이동하고' 그 위치부터 시작해 첫번째 매개변수로 주어진 String 객체값을 찾아 찾으면 그 첫 문자의 인덱스 번호를 반환

String hello = "HelloWorld_MyWorld";
System.out.println(hello.lastIndexOf("World")); // => 13 반환 (myWorld)
System.out.println(hello.lastIndexOf("World", 10)); // => 5 반환 (HelloWorld)

+) 만약 IndexOf, lastIndexOf 둘다 해당 문자열을 못 찾을 경우 -1값 반환

++) ASCII 코드와 같이 쓰면 이런 응용도 가능하다.

String hello = "HelloWorld_MyWorld";
System.out.println(hello.indexOf(65)); // => ASCII 코드상 65는 대문자 A를 뜻함 
//대문자 A는 hello String 객체에 없으므로 그래서 결과값은 -1 
System.out.println(hello.indexOf(99)); // => ASCII 코드상 65는 소문자 c를 뜻함
//소문자 c는 hello String 객체에 없으므로 그래서 결과값은 -1

∴ indexOf 혹은 lastIndexOf와 substring을 잘 조합하면 웹 URL에서 특정 코드를 추출해낼수 있다.

contains(): 해당 String 객체에서 주어진 매개변수 문자열을 포함하는지 체크하고 있으면 true, 없으면 false를 반환

String str = "my java test";
		
		System.out.println(str.contains("java")); //contains 메소드는 해당 문자열이 있는지 체크하는 메소드 => true
		System.out.println(str.contains(" my")); //공백 구별함 => false
		System.out.println(str.contains("JAVA")); // 대소문자 구별함 => false
		System.out.println(str.contains("java test")); //일부 문자열 구별함 => true

replace, replaceAll(): 매개변수를 두 개로 받는데 첫번째 매개변수로 주어진 String 객체를 모두 찾아서 두번째 매개변수로 주어진 또 다른 String 객체로 바꿈 (replace, replaceAll 모두 동일)

		String b = "Welcome to Java World Java World";
		System.out.println(b.replace("Java", "Computer")); //replace 메소드는 해당 문자열을 찾은 다음 그 문자열을 해당 문자열을 두번째 매개변수 값으로 모두 대체함 
		System.out.println(b.replaceAll("Java", "Computer")); //replaceAll도 일단 동일함
        //결과는 둘 다 Welcome to Computer World Computer World 출력

+) replaceAll과 대괄호를 이용하면 특정 문자들을 싹 바꿀수 있다.

String str = "abcdefghijk";
		System.out.println("result ===> " + str.replaceAll("[abchij]", "굿")); //replaceAll(배열 처리 "[바꾸려는 특정 '문자' 모음]", "") 두번째 매개변수로 모두 다 바꿈
		//결과는 result ===> 굿굿굿defg굿굿굿k 출력        
		System.out.println("result ===> " + str.replaceAll("[^abchij]", "굿")); //^ not 반대 처리 => 단어 아닌 것들 나머지 두번째 매개변수로 바꿈
        //결과는 result ===> abc굿굿굿굿hij굿 출력

toUpperCase()/toLowerCase():String 객체의 모든 문자를 대문자로/소문자로 변경해 반환

		String a = "Welcome to Java World";
		System.out.println(a.toUpperCase()); //대문자 변경 //=> WELCOME TO JAVA WORLD 
		System.out.println(a.toLowerCase()); //소문자 변경 //=> welcome to java world

이렇게 해서 String 클래스로 자주 쓰이는 주요 메서드들을 알아 보았고, 아래 마지막 예시는 앞서 배운 메소드들을 활용해 공백을 지워보는 결과를 만드는 코드문이다.

String str4 = "   공백  제거    공백  제거   "; //(3) (2) (4) (2) (3) 각각 공백 갯수
		//str4 = str4.replaceAll(" ", ""); 이 코드 한줄로 공백 제거 가능
		// str4 = str4.replaceAll("[^공백제거]",""); 이 코드 한줄로 공백 제거 가능
		str4 = str4.trim(); //앞 뒤 공백 제거
		System.out.println(str4); //공백  제거    공백  제거 출력
		String str5 = str4.substring(str4.indexOf("공"), 6);
		System.out.println(str5); //왼쪽 공백  제거 출력
		String str6 = str5.replaceAll(" ", "");
		System.out.println(str6); //왼쪽 공백제거 출력
		String str7 = str4.substring(str4.lastIndexOf("공"), 16);
		System.out.println(str7); //오른쪽 공백  제거 출력
		String str8 = str7.replaceAll(" ", "");
		System.out.println(str8); //오른쪽 공백제거 출력
		String str9 = str6.concat(str8);
		System.out.println(str9); //(왼쪽) 공백제거공백제거 (오른쪽) 출력

이렇게 우리가 앞에서 살짝 간단히 하고 넘어갔던 클래스, 객체 그리고 인스턴스를 좀 더 자세히 의의를 생각하면서 배워보았고 자바를 하면서 많이 활용하는 객체 유형, 배열 객체와 String 클래스 객체에 대해 배워보았다.

다음장은 이것도 우리가 살짝 간단히 보았었던 자바의 메모리 영역 구조, 정확히는 static 메모리/heap 메모리/Stack 메모리에 대해 알아보겠다.

0개의 댓글