📚 Study/Java

JAVA :: Test136~137_자바에서 기본적으로 제공하는 주요 클래스들(String 클래스)

bono-hye 2023. 9. 18. 23:56

String 클래스

equals(), substring(), equalsIgonoreCase(), indexOf(), endsWith(), lastIndexOf(), charAt(), compareTo(), replaceAll(), trim(),...

 

○ String 클래스

  • String 클래스는 내부 문자열에 대한 수정이 불가능하다. (참조하는 주소가 변경되는 것이지 내용 자체가 변경되는 것이 아님)
  • 즉, 내용 불변(immutable) 
  • 문자열의 내용이 변경되면 새로운 객체를 생성하며 참조 대상을 잃어버린 객체는 가비지 컬렉션의 대상이 되고, 새로운 객체에 새 주소를 할당하게 되므로 해시코드도 변하게 될 수 있다.
  • String 클래스 간에 「+」 연산자를 사용하면 문자열 간의 결합이 가능
  • String 클래스와 다른 클래스 객체, 또는 기본형 데이터 간에 「+ 연산자를 사용하는 경우에도 내부적으로 자동 String 클래스로 변환 가능
    • 시각적으로 확인되는 결과는 이렇지만, String은 내용을 변경할 수 없기 때문에 「+ 연산자를 사용하게 되면
    • 내부적으로 StringBuffer를 생성하여 append() 메소드를 이용하여 문자열에 대한 결합 수행
    • => 정적인 문자열을 처리하는 경우에는 주로 String 클래스 사용
    • => 동적인 문자열을 처리하는 경우에는 StringBuffer 클래스를 사용하는 것이 효율적

 

○ String  객체의 생성 및 특징

  • String 객체를 생성하는 방법은 2가지가 있다.
    • ① 문자열을 상수로 지정하는 방법
      • String str1 = "Java";
    • ② String 클래스의 생성자를 이용하는 방법
      • String str2 = new String("Java");
  • 하지만, 문자열 상수를 대입 연산자를 사용하여 지정하는 방법인 ①과 new 연산자를 이용하여 객체를 생성하는 방법인 ②은 내부적으로 의미가 다르다.

▼ Test136

public class Test136
{
	public static void main(String[] args)
	{
		String s1 = "seoul";
		String s2 = "seoul";
		String s3 = new String("seoul");
		String s4 = new String("seoul");

		System.out.println("s1 : " + s1);
		System.out.println("s2 : " + s2);
		System.out.println("s3 : " + s3);
		System.out.println("s4 : " + s4);
		//--==>> s1 : seoul
		//       s2 : seoul
		//	     s3 : seoul
		//	     s4 : seoul

		System.out.println("s1 == s2 : " + (s1 == s2));		// 주소값 비교함!
		System.out.println("s2 == s3 : " + (s2 == s3));
		System.out.println("s3 == s4 : " + (s3 == s4));
		System.out.println("s4 == s1 : " + (s4 == s1));
		//--==>> s1 == s2 : true
		//		 s2 == s3 : false
		//		 s3 == s4 : false
		//		 s4 == s1 : false

		// ※  s1과 s2 객체가 참조하는 문자열 상수가 동일한 경우
		//	  문자열이 저장된 기억 장소의 영역이 동일하기 때문에
		//	  s1 객체와 s2 객체는 동일한 기억장소를 참조하게 된다.
		//	  하지만,
		//	  s3 와 s4 는 동일한 영역이 아닌 다른 기억 공간을
		//	  새롭게(new) 확보하여 문자열 상수를 그 공간에 대입한 경우이므로
		//	  두 인스턴스는 같은 영역을 참조하는 것이 아니다.
		//	  따라서, 『s3 == s4』는 거짓이 되며
		//	  만약, 같은 문자열 상수인지의 여부를 비교해야 할 경우라면
		//	  『equals()』 메소드를 이용해야 한다.

		// ※ String 클래스는 Object 의 equals() 를 Overriding~!!!
		// equals Object 클래스에서는 주소 비교, String 클래스에서는 오버라이딩해서 그 문자 자체를 비교

		System.out.println("s1.equals(s2) : " + s1.equals(s2));
		System.out.println("s2.equals(s3) : " + s1.equals(s3));
		System.out.println("s3.equals(s4) : " + s1.equals(s4));
		System.out.println("s4.equals(s1) : " + s1.equals(s1));
		//--==>> s1.equals(s2) : true
		//		 s2.equals(s3) : true
		//		 s3.equals(s4) : true
		//		 s4.equals(s1) : true


		System.out.println("s1 : " + s1.hashCode());
		System.out.println("s2 : " + s2.hashCode());
		System.out.println("s3 : " + s3.hashCode());
		System.out.println("s4 : " + s4.hashCode());
		//--==>> s1 : 109324212
		//		 s2 : 109324212
		//		 s3 : 109324212
		//		 s4 : 109324212

		// ※ 객체가 같으면 hashcode 가 같지만
		//	  hashcode 가 같다고 해서 같은 객체는 아니다~!!!

		s2 += "korea";
		System.out.println("s2 : " + s2);
		//--==>> s2 : seoulkorea

		s2 = "korea";
		System.out.println("s2 : " + s2);
		//--==>> s2 : korea

		//-- 이와 같은 경우
		//	 s2 가 참조한 "seoul"이 저장된 영역은
		//	 『s2 += "korea";』 가 수행되는 시점에서
		//	 해당 영역의 값이 변경되는 것이 아니라
		//   가비지 컬렉션의 대상이 되며,
		//	 "seoulkorea" 상수가 저장된 영역을
		//	 s2 가 참조하게 되었다가
		//	 다시 s2 가 참조한 "seoulkorea"가 저장된 영역은
		//	 『s2 = "korea";』가 수행되는 시점에서
		//	 가바지 컬렉션의 대상이 되며,
		//	 "korea" 문자열 상수가 새롭게 저장된 영역을
		//	 s2가 참조하게 된다.
		//
		//==> ※ String  객체의 내용은 불변이다~!!!
	}
}

 

▼ Test137

public class Test137
{
	public static void main(String[] args)
	{
		String s = "seoul korea";
		System.out.println("s : " + s);
		//--==>> s : seoul korea


		// ○ 문자열 추출
		System.out.println(s.substring(6, 9));
		//--==>> kor

		// ※ 『String.substring(s, e)』
		//	  String 문자열을 대상으로
		//	  s 번째에서... e-1 번째까지 추출
		//	  (단, 인덱스는 0부터 시작)

		System.out.println(s.substring(7));
		//--==>> orea

		// ※ 『String.substring(s)』
		//	  String 문자열을 대상으로
		//	  s 번째에서... 끝까지 추출
		//	  (즉, 문자열이 가진 길이만큼...)
		

		// ○ 문자열의 데이터(값) 비교
		System.out.println(s.equals("seoul korea"));
		System.out.println(s.equals("seoul Korea"));
		//--==>> true
		//	     false
		//-- 대소문자 엄격히 구분

		System.out.println(s.equalsIgnoreCase("SEOUL KOREA"));
		//--==>> true
		//-- 대소문자 구분 안함


		// ○ 찾고자하는 대상 문자열(s)에
		//	  『kor』 문자열이 존재할까?
		//	   존재한다면... 그 위치는 어떻게 될까?

		// "seoul korea"
		// 0123456789
		
		System.out.println(s.indexOf("kor"));			// 대상 문자열의 위치 찾는 메소드
		//--==>> 6

		System.out.println(s.indexOf("ea"));
		//--==>> 9

		System.out.println(s.indexOf("e"));
		//--==>> 1
		//-- 먼저 찾은 문자열의 인덱스를 반환하고 종료. (seoul에도 e가 있고 korea에도 e가 있는데 먼저 발견된 e만 반환하고 뒤에 e는 찾지 않음)

		System.out.println(s.indexOf("tt"));
		//--==>> -1
		//-- 찾고자 하는 문자열이 대상 문자열에 존재할 경우
		//	 그 문자열의 인덱스를 반환하지만
		//	 존재하지 않을 경우 음수를 반환하게된다. → (-1)


		// ○ 대상 문자열(s)이 『rea』로 끝나는지의 여부 확인
		//	  (true / false)
		System.out.println(s.endsWith("rea"));
		System.out.println(s.endsWith("oul"));
		//--==>> true
		//		 false

		// ○ 찾고자하는 대상 문자열(s)에
		//	  『e』 문자열이 존재할까?
		//	   존재한다면... 그 위치는 어떻게 될까?
		//	   (단, 뒤에서 부터 검사)
		
		// seoul korea  앞에서 부터 검사
		System.out.println(s.indexOf("e"));
		System.out.println(s.indexOf("o"));
		//--==>> 1
		//		 2

		// seoul korea  뒤에서 부터 검사 (단, 위치는 앞에서 부터)
		System.out.println(s.lastIndexOf("e"));
		System.out.println(s.lastIndexOf("o"));
		//--==>> 9
		//		 7


		// ○ 대상 문자열(s) 중
		//	  『6』번째 인덱스 위치의 문자는?

		// seoul korea
		System.out.println(s.charAt(6));
		//--==>> k

		// seoul korea
		//System.out.println(s.charAt(22));
		//--==>> 에러 발생(런타임 에러)
		//       StringIndexOutOfBoundsException


		// ○ 대상 문자열(s)과 비교 문자열 『seoul corea』 중
		//	  어떤 문자열이 더 큰가?		→ 문자열에 대한 크기 비교?
		//	  ==> 두 문자열이 같다면		→ 0
		//	  ==> 두 문자열이 다르다면		→ ???

		// seoul korea
		System.out.println(s.compareTo("seoul korea"));
		//--==>> 0 → 두 문자열이 같다. (s 의 값과 "seoul korea" 의 값이...)
		System.out.println(s.compareTo("seoul corea"));
		//--==>> 8
		//-- c ~ k → defghijk → 8

		// ○ 대상 문자열(s) 중
		//	  해당 문자열을 찾아서 원하는 형태로 수정된 문자열 반환
		s = "우리나라 대한민국 대한독립 만세";
		s = s.replaceAll("대한", "자주");		// 원본 대상이 바뀌지 않음. 따라서 다시 s에 값을 넣어줘야 함
		System.out.println("처리 결과 : " + s);
		//--==>> 처리 결과 : 우리나라 자주민국 자주독립 만세

		// ○ 공백 제거
		s = "     사    랑    ";

		//System.out.println(s);					// 공백 확인이 안되어서 아래로 다시 확인해보자
		//--==>>      사    랑    
		System.out.println("|" + s + "|");
		//--==>>|     사    랑    |


		System.out.println("|" + s.trim() + "|");	// 손톱깎이 생각 → 가장자리만 없앨 수 있음. 가운데만 제거 못함
		//--==>>|사    랑|
		//--==>> 양쪽 가장자리 공백 제거

		System.out.println("|" + s.replaceAll(" ","") + "|");
		//--==>> |사랑|
		
		// "50"
		int temp = Integer.parseInt("50");
		//System.out.println(temp);		// 정수형으로 변경되었는지 확인이 불가하니까 아래 코드로 바꿔서 확인~
		System.out.printf("%d\n", temp);
		//--==>> 50

		// 30
		s = Integer.toString(30);
		//System.out.println(s);		// 문자열로 변경되었는지 확인이 불가하니까 아래 코드로 바꿔서 확인~
		System.out.printf("%s\n", s);
		//--==>> 30


		int n = 2354678;
		System.out.printf("%d", n);
		System.out.format("%d", n);
		//-===>> 2354678
		//		 2354678

		System.out.println();		// 개행

		s = String.format("%d", n);
		System.out.println(s);
		//--==>> 2354678

		s = String.format("%.2f", 123.456);
		System.out.println(s);
		//--==>> 123.46

		s = String.format("확인 : %b", true);
		System.out.println(s);
		//--==>> 확인 : true


		s = String.format("결과 : %,d", n);
		System.out.println(s);
		//--==>> 결과 : 2,354,678


		//String str = "기본,열정,배려";
		//String[] strArr = str.split(",");

		// line 182 ~ 183 과 동일한 구문
		String[] strArr = "기본,열정,배려".split(",");

		for (String str : strArr)
			System.out.print(str + " ");
		System.out.println();
		//--==>> 기본 열정 배려

	}
}