본문 바로가기

코딩공부일지/수업 review

API

Part1. String 클래스

1. String클래스타입 객체생성 

 1) new 키워드 + 생성자호출을 통한 객체 생성

     <메모리에서 일어나는 일>

 일반 참조자료형 변수 객체생성과 동일하게
 "new" 사용시마다 heap 영역에 문자열을 담고 있는 새로운 객체(새로운 주소값) 생성
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = new String("가나다");
String str4 = new String("가나다");

==> 상단 str1~str4는 모두 상이한 주소값을 가짐

 

 2) 대입연산자를 통해 직접 값을 대입하여 생성: 문자열 리터럴 생성 방식

    <메모리에서 일어나는 일 >

2. 대입연산자를 통해 직접 값을 넣어서 생성 :
   객체 생성 이전 heap영역의 constant pool -  String pool로 이동하여 같은 문자열 내용이 존재하는지 확인
     ==> 같은 문자열 존재시 : 신규 주소값을 만들지 않고 기존 주소값을 반환 (중복 제거)
            중복에 의한메모리 낭비가 없음  
     ==> 같은 문자열이 없을 시 : 신규 주소값 생성 및 주소값 반환

https://www.javaguides.net/2018/07/guide-to-java-string-constant-pool.html

String str1 ="abc";
String str2 ="abc";
String str3 = "가나다";
String str4 = "가나다";


주소값 비교시 : str1 == str2,  st3==str4

 

2. String클래스의 특징

   1) toString, equals, hashCode메서드 오버라이딩

1] toString(): String
   - 출력문에서 호출 시 String객체가 담고 있는 실제 문자열이 출력되도록 오버라이딩
2] equals(): boolean
 - String객체가 담고있는 실제 문자열을 비교한 결과를 반환하도록 오버라이딩
3] hashCode(): int
 - 객체의 주소값을 해싱하는 것이 아닌, 실제 문자열을 기반으로 해싱한 hashCode를 반환하도록 오버라이딩
   (동일한 문자열을 기반으로 해싱하였을 경우 hashCode 결과가 같음)
		String str1 = new String("hello");
		String str2 = new String("hello");
		System.out.println(str1);  
         =-> 참조자료형 출력시 .toString(주소값 반환메서드)이 붙어 해당 객체주소값이 출력됨 
         --> String형 출력시 주소값이 아닌 문자열 출력됨
             (String 클래스에서 toString이 문자열을 출력하도록 오버라이딩 되어있음을 의미)
									
      1] String클래스 equals()메서드 오버라이딩 (문자열비교) 
		System.out.println(str1.equals(str2)); / true
		System.out.println(str1 == str2); / false, str1과 str2는 서로 다른 객체를 참조하는 주소값
		
      2] String클래스 hashCode()메서드 오버라이딩 (문자열 같을시 같은 주소값 반환)   
		System.out.println(str1.hashCode()); / 서로 다른 두 객체의 hascode값(주소를 10진수로 반환)은 원래 달라야 한다! 
		System.out.println(str2.hashCode());  
        / 그러나 출력해보면 상단 두 개의 주소값이 같음
          (String클래스에서 문자열 비교하도록 오버라이딩)
        
        
      3] identityHashCode : String클래스에서도 실제 주소값을 출력함
		System.out.println(System.identityHashCode(str1)); // 실제주소값을 출력하면 두 값이 다름
		System.out.println(System.identityHashCode(str2));
		String str1 = "hello";    
     =>   constant pool의 String pool에
          바로 신규객체를 생성하는 것이 아닌, 기존 보유객체 확인 후 중복값 없을시에만 신규생성
		String str2 = "hello";        
		System.out.println(str1);
		System.out.println(str2);
		
		System.out.println(str1.equals(str2)); // true
		System.out.println(str1.hashCode()); // 99162322
		System.out.println(str2.hashCode()); //99162322
		System.out.println(System.identityHashCode(str1)); //1829164700
		System.out.println(System.identityHashCode(str2));  //1829164700
        System.out.println(str1 == str2); // true

 

  2) String 클래스는 불변(immutable)객체

      : String클래스 객체가 변수에 할당되면 참조를 업데이트하거나 내부 상태를 어떤 방법으로도 변경할 수 없음

        변수에 새로운 값을 대입하면,  참조를 업데이트하는 것이 아니라

        새로 생성한 객체(또는 기존 String pool에 존재하는 객체)의 주소값을 새로 대입하는 개념

        (변수와 연결이 끊긴 기존 객체는 GC가 치워줌) 

 

    String str = "hello";
	    System.out.println(System.identityHashCode(str));  // 1829164700
		
      ==> string pool 내에 문자열 "hello"가 가지고 있는 주소값 반환
  
        
        str = "Goodbye";
      ==> *String은 불변클래스이므로, 기존 객체에 새로운 값 저장이 불가함
      ==> 새로운 값을 대입했을 경우,
          우선적으로 heap 영역 Constant Pool에서 Goodbye 문자열 검색 후
          존재할 경우 해당 주소를 str에 대입,
          존재하지 않을 경우 새로운 객체를 생성하여 신규 주소값을 str에 대입
          변수와 연결이 끊긴 객체 "hello"는 gc가 치워줌
		System.out.println(System.identityHashCode(str));  // 2018699554
		// str 에 "Goodbye"대입시

3. StringBuffer / StringBuilder

  - String클래스의 특징, "불변성"으로 인한 문자열 조작시의 메모리 낭비 해결법

 String형 변수는 조작(수정, 추가, 삭제)시마다 새로운 공간을 할당 --> 메모리 낭비 발생!
이를 막기 위해 임시공간(buffer)을 준비 ,
임시공간에 문자열을 담아두었다가 한번에 처리하는 StringBuffer, StringBuilder 클래스가 있음
(동시제어기능 유무에 따라 나뉨)

   1) StringBuffer   

동시제어 기능 있음 
* Thread-safe란: 멀티스레드프로그래밍에서 어떤 변수에 동시 접근시 안전변경을 보장

    - append: 기존 문자열에 문자열을 이어붙이는 메서드

StringBuffer sb = new StringBuffer(); 
sb.append( 추가할 문자열 );
		StringBuffer sb = new StringBuffer();
		sb.append("hello");
		System.out.println(sb.hashCode()); // 1829164700
		System.out.println("hello".hashCode()); // 99162322
		
		sb.append("World!");
		System.out.println(sb.hashCode());  // 1829164700
		System.out.println("helloWorld!".hashCode());// -933562815
		System.out.println(sb); // helloWorld!

  - insert메서드 

StringBuffer sb = new StringBuffer(); 
sb.insert(추가를 시작할 index, 추가할 문자열 );
	StringBuffer sb = new StringBuffer();
		  sb.append("this is Friday.");
		  sb.insert(8, "happy happy ");
		   System.out.println(sb);  // this is happy happy Friday.

 - subString메서드

StringBuffer sb = new StringBuffer(); 
sb.insert(삭제를 시작할 index, 끝 index );
StringBuffer sb = new StringBuffer();
	sb.append("Time to go Home");
	System.out.println(sb.substring(0, 4)); // to go home

 2) StringBuilder

StringBuffer와 동일기능
동시제어(Thread Safe)기능이 없는 클래스 
간단 프로그램, 동시제어를 다른프로그램이 제공하는 경우 사용

 

4. 기타 String클래스 메서드

 1. 문자열.charAt(int index) : char
		char ch = str1.charAt(4);
		System.out.println(ch);
		
2. 문자열.concat(String str) : String
	 기존 문자열에 전달받은 또 다른 문자열을 하나로 합쳐서 반환
	 문자열 + 전달받은 문자열
		String str2 = str1.concat("!!!");
		System.out.println("str2 : "+str2);
		
3. 문자열.length() : int
   문자열의 길이 반환
		System.out.println("str1의 길이: "+ str1.length());

 4-1 문자열.substring(int beginIndext) : String
     문자열의 beginIndex의 위치에서 문자열 끝까지의 문자열을 추출하여 리턴
 4-2 문자열.substring(int beginIndext, endIndex) : String
     문자열의 beginIndex의 위치에서 endIndex-1 까지의 문자열을 추출하여 리턴	
		System.out.println(str1.substring(6));
		System.out.println(str1.substring(0, 6));
        
 5. 문자열.replace(char old, char new) :String
    문자열에서 old문자를 new문자로 변환한 문자열을  리턴
		String str3 = str1.replace('l', 'x');
   ==> str1은 불변자료형이므로 내용이 바뀌는게 아니라 바뀐 값을 리턴 => 새로운 변수에 담아주기
		System.out.println(str3);
 6. 문자열.trim() :String
   --> 문자열의 맨 앞과 맨뒤의 공백을 제거한 문자열을 리턴
		String str4 = "  집  에  갈      래   ";
		System.out.println(str4.trim());
		
 7. toUpperCase() ==> 모든 문자열 대문자로
    toLowerCase() -> 모든 문자열 소문자로
		System.out.println(str1.toUpperCase());
		System.out.println(str1.toLowerCase());
        
  8. 문자열.toCharArray() :char[]
	 문자열의 각 문자들을 char[]형 배열에 옮겨담은 후 해당배열 리턴
		char[] chArr = str1.toCharArray();

 

5. String Tokenizer : 문자열 분리하기

1) 구분자를 제시하여 해당 문자열을 분리하는 방법 (배열) 
2) 분리된 각각의 문자열을 토큰으로 취급하는 방법 (토큰)

  1) split

문자열.split(String구분자) : String[ ] ==> String형 배열을 반환한다 (인덱스에 각 값을 담아서 반환)
String[] arr = str.split(",");
		
        1] 일반 for문을 이용한 배열내용(인덱스)출력
		for( int i =0; i < arr.length ; i++) {
			System.out.println(arr[i]);
		}
        
        2] 향상된 for문을 이용한 배열내용 출력
		for(String s: arr) {
			System.out.println(s);
		}

  2) String Tokenizer이용

1. 객체 생성

  StringTokenizer stn = new StringTokenizer(문자열, 구분자)


2.  java.util.tokenizer 클래스 임포트

   [1] 생성자

   

public StringTokenizer(String str); 전달된 매개변수 str을 default delim으로 문자열 분리
(  \t,\n,\r)
public StringTokenizer(String str,String delim);  delim(두 번째 매개변수)로 문자열을 분리
public StringTokenizer(String str,String delim,boolean returnDelims); str을 delim을 기준으로 분리시
token에 delim 포함여부 (true -> 포함, false->불포함)

 [2] 주요메소드

countToken : int 토큰의 개수 리턴
nextToken() : String
nextToken (String delim)
nextElement(): Object
다음 토큰 리턴, 리턴후 해당 토큰은 삭제됨
(탐색후 소비됨)
hasMoreToken() : boolean
hasMoreElement() : boolean
리턴할 다음토큰이 있는지 여부 확인 (t/f)
	StringTokenizer stn = new StringTokenizer(new String("오늘은 즐거운 기차여행 가는 날")," ");
	System.out.println("분리된 문자열 갯수: "+stn.countTokens());
	//  ==> .countTokens() 구분자로 분리된 문자열이 몇개인지 반환해주는 메서드
	for (int i=0; i <stn.countTokens(); i++) {
		System.out.println(stn.nextToken());
	}
	
	StringTokenizer stn2 = new StringTokenizer(new String("오늘은 즐거운 기차여행 가는 날")," ");
	System.out.println("분리된 문자열 갯수: "+stn2.countTokens());
	while (stn2.hasMoreTokens()) {
		System.out.println(stn2.nextToken());		
	
    
    
분리된 문자열 갯수: 5
오늘은
즐거운
기차여행
가는
날

 

3) StringTokenizer와 Spilt의 차이

 

  - StringTokenizer는 문자 또는 문자열로 문자열을 구분한다면, split는 정규표현식으로 구분합니다.

 

StringTokenizer는 빈 문자열을 토큰으로 인식하지 않지만 split는 빈 문자열을 토큰으로 인식하는 차이가 있습니다.

 

StringTokenizer는 결과값이 문자열이라면 split는 결과 값이 문자열 배열입니다.

따라서 StringTokenizer를 이용할 경우 전체 토큰을 보고싶다면 반복문을 이용해 하나하나 뽑을 수 밖에 없습니다.

 

Part2

1. Wrapper클래스란?

- 기본자료형을 객체(참조자료형)로 포장해주는 클래스
* * boolean, char, byte, short, int, long, float, double <--->
  * Boolean, Character, Byte, Short, Integer(중요), Long, Float, Double

기본자료형을 객체로 취급해야 하는 경우(Wrapper클래스가 필요한 때):
메소드의 매개변수로 기본자료형이 아닌 객체타입이 들어가야할 떄 *
다형성을 적용시키고 싶을 떄
	int num1 = 10;
	int num2 = 15;
		
  *  num1과 num2동등비교
		System.out.println(num1== num2);          : 기본형 연산시 주소값이 하닌 실제 저장값 비교, 결과:false 
  	 	System.out.println(num1.equals( num2) );  : 오류! equals는 Object클래스 메서드 (주소값을 비교하는메서드) 
													 Object는 모든클래스의 최고조상, Object메소드는 참조자료형 어디서든 쓸수있다
													 그러나 기본자료형은 객체가 아니므로 Object메소드를 상속받지 못함
													 ==? 기본자료형의 주소값을 비교하고 싶을때==> 객체화가필요할 떄
		
		// Integer i1 = new Integer(num1);  이렇게 쓰지 않고
		Integer i1 = num1;
		Integer i2 = num2;
		System.out.println(i1.equals(i2));

 

 

 

 

 

 

 

 


  <기타>

1. 연산자 우선순위 복습

		String a = "a";
		String b = "a";
		System.out.println("결과 : "+ a==b); //  결과 : false ! 						
        / 연산자 우선순위에 의해서  ("결과: "+a ) 가 먼저 수행됨 
		System.out.println("결과 : "+ (a==b)); //  결과 : true

 

thread란?

thread safe, 동기화란?

향상된 for문

향상된 for문:
초기, 조건, 증감식 없음
배열처럼 여러 요소, 인덱스로 이루어진 집합의 모든 요소에 대해
특정 작업을 반복하기 위해 사용 (ArrayList요소, 배열 인덱스 출력 등)
단순출력만 가능하며 배열의 값 수정불가
[표현법]
for (배열a의 각 인덱스를 받아줄 변수:순차적으로 접근할 배열a) {

}

  * 일반 for문과 비교

String[] sArr = {"오늘은 토요일"};
    for( int i=0; i <sArr.length; i++) {
     		System.out.println(sArr[i]);
     }

초기식, 조건식(배열의 길이), 증감식
그리고 인덱스에 지역변수 대입까지
번거롭다!


String[] sArr = {"오늘은 토요일"};
    for( String str : sArr ) {
     		System.out.println(str);
     }
      
 배열명만 가지고
 배열을 받아줄 변수 지정 후 출력가능
 String클래스의 경우 변수명으로 바로 출력가능 (toString오버라이딩)