복습 / 과제 설명
https://laker99.tistory.com/20?category=1065834
- Calendar 클래스 로 날짜 시간 요일 까지 출력
- 새로 만드는게 아니라 시스템으로부터 구해오는 클래스라서 Calendar 클래스는 new 연산자로 객체 못만듬
Calendar 객체 생성법
1.
Calendar c1 = new GregorianCalendar
- 이미 형성된 상속관계, 자식 클래스인 GregorianCalendar 로 객체를 만들어서 왼쪽의 부모에게 전달 = 레퍼런스 형변환
- 자식 객체가 부모에게 전달 = 업캐스팅
- 세번째 형변환인 레퍼런스 형변환이며, 두 클래스 사이에 상속관계가 전제되어야만 가능함
2.
Calendar c = Calendar.getInstance();
- Calendar 클래스 안의 정적메소드 getInstance() 메소드 사용해서 객체를 구해옴, Calnedar 객체를 받음
* 객체 = 인스턴스
- 년월일시분초 -> Calendar의 정적필드를 이용해서 구해야함(API 문서)
- 클래스명.필드명 으로 필드 사용
- 연도 구해올땐 Calendar.YEAR 필드로 get함수써서 구함
int y = c.get(Calendar.YEAR);
int m = c.get(Calendar.MONTH) + 1; // 0~11 이므로 +1 해주기
int d = c.get(Calnedar.DATE);
int h1 = c.get(Calendar.HOUR); // 12시간
int h2 = c.get(Calendar.HOUR_OF_DAY); // 24시간
int ap = c.get(Calendar.AM_PM); // 오전 0 오후 1
int w = c.get(Calendar.DAY_OF_WEEK); //1~7 을 돌려줌
- 1,2,3,4,5,6,7 로 일정히 증가하므로 숫자를 요일로 변환시켜주기 위해서는 String[] 클래스 배열을 사용한다
int w = c.get(Calendar.DAY_OF_WEEK);//1~7
System.out.println("w="+w);
// 1:일, 2:월, 3:화, 4:수, 5:목, 6:금, 7:토
String[] week={"일","월","화","수","목","금","토"};
System.out.println(week[w-1]+"요일");
- 이렇게 배열인덱스와 맞춰주면 됨
- "금" 은 6이 나오는데 String배열에는 인덱스 5번이므로 -1 해줌
문자열 처리 클래스 종류
- String, StringBuffer, StringTokenizer
1. String : 문자열을 저장함, 가장 빈도 높은 사용
2. StringTokenizer : 여러 문자들을 구분기호로 파싱할때 사용
3. StringBuffer - 가장 빈도 낮지만 알아야함
문자열 처리 클래스 차이
- 3개의 클래스가 기능이 조금씩 다르다.
- 메모리 상에서 데이터 처리하는데 차이가 있다
- String 클래스의 메소드 아주 많다
String 클래스와 메소드
- 자바에서 가장 사용빈도 높은 클래스
- java.lang 패키지 안, import필요 없다
- 지원되는 메소드 100개 넘음
String 클래스 예제1
- StringTest00.java
package p2022_07_01;
class StringTest00 {
public static void main(String[] args) {
String str1 = new String("Java Programming");
String str2 = new String("Java Programming");
if (str1 == str2) { // 주소 비교
System.out.println("같다");
} else {
System.out.println("다르다"); // 다르다
}
String str3 = "Java Programming";
String str4 = "Java Programming";
if (str3 == str4) {
System.out.println("같다"); // 같다
} else {
System.out.println("다르다");
}
if (str1.equals(str3)) { // 값 비교
System.out.println("같은 값");
} else {
System.out.println("다른 값");
}
}
}
다르다
같다
같은 값
- String 클래스만 new를 써도 되고 그냥 String name = "mimi" 라고 할 수도 있다
- new연산자 쓸때마다 매번 힙메모리상에 새로운 공간을 생성하라는 표시
- 힙메모리상에 "Java Programming"을 저장하고 있다
- 여기서 str3와 str2의 주솟값이 같을까? 즉 같은 "Java Programming"일까?
-> 아니다 위에서든 밑에서든 new를 쓰면 그냥 단독으로 새로운 공간 가지는거임
- str3에서 힙에 Java Programming 만들어졌으므로
- String str4 = "Java Programming"; 하면 그냥 str4는 이미 str3때 만들어진 값의 주솟값을 리턴받음
-> str3 == str4 같다 (같은 주소다)
그림
참조형의 비교대상 2개
1. 비교연산자로 주솟값 비교
2. equals로 값을 비교
String 클래스 예제2
- ConnectString.java
package p2022_07_01;
public class ConnectString {
public static void main( String[] args ) {
// String 객체 선언
String gemini = "gemini";
String johnharu = "johnharu";
// 두 String 객체를 "+" 연산 수행
String tempString1 = gemini + johnharu;
System.out.println( tempString1 );
System.out.println( "gemini" + "johnharu" );
// String + 정수형
String tempString2 = tempString1 + 100;
System.out.println( tempString2 );
}
}
geminijohnharu
geminijohnharu
geminijohnharu100
위 예제 부분1
String tempString1 = gemini + johnharu;
System.out.println( tempString1 );
- 객체 + 객체 를 쓰면 주솟값이 아닌 가리키는 값들끼리를 연결해준다
위 예제 부분2
System.out.println( "gemini" + "johnharu" );
- 이렇게해도 연결되어 출력된다
String형 자료형과 기본자료형 변수끼리 결합(위 예제 부분3)
// String + 정수형
String tempString2 = tempString1 + 100;
System.out.println( tempString2 );
- String형 자료형과 기본자료형 변수끼리 산술적인 연산 +가 안된다
- 붙어서 geminijohnharu100이 출력되고 결과는 전체가 String형으로 바뀜
String 클래스 예제3(String과 메모리)
- StringTest01.java
package p2022_07_01;
// String 객체를 생성한 후에 메소드에 의해서 값의 변화가 일어나면
// 변경된 값을 힙메모리 영역에 다시 저장 한다.
// Garbage Collection 기능 (쓰레기 수집 기능)
// : 재사용할 수 없는 힙메모리 영역의 데이터를 모아서 지워주는 기능
class StringTest01 {
public static void main(String[] args) {
String str1 = "Java Programming";
str1.toUpperCase(); // 대문자로 변환
System.out.println(str1); //메서드 호출 후에도 str1의 내용은 수정되지 않는다.(원래값출력)
System.out.println(str1.toUpperCase()); //대문자 변환된 내용 출력
String str2=str1.toUpperCase(); //메소드의 처리 결과를 str2에 저장
System.out.println(str2); //대문자 변환된 내용 출력
}
}
Java Programming
JAVA PROGRAMMING
JAVA PROGRAMMING
위 예제의 부분1
str1.toUpperCase(); // 대문자로 변환
System.out.println(str1); //메서드 호출 후에도 str1의 내용은 수정되지 않는다.(원래값출력)
- 왜 위의 예제에서 str1.toUpperCase() 하면 str1의 값을 출력했을때 대문자로 변환되어 출력되지 않을까?
- String class는 값의 변화가 일어나면 변경된 값을 힙메모리상에 저장시킴
- 하지만 이 변경된 값을 재사용하지 못할때는 가비지 콜렉터가 변경이 되더라도 지워버림
- 즉 대문자로 변경이 되었지만 가비지콜렉터 기능때문에 재사용을 못하기 때문에 그 값을 지워버리고 처음 원래의 값(소문자)을 출력시킴
- Java Pro 에서 str1.toUpperCase() 를 쓰면 바뀐 내용(대문자) 를 힙메모리상에 새로 저장해줌
(그림 있음 2번번호)
- 하지만 접근하는방법이 없고, 재사용이 안되기 때문에 가비지 콜렉터가 지워버림
- 그래서 str1을 출력하면 원래값을 출력함
- 힙메모리상에서 값의 변화가 일어나면 매번 그걸 힙메모리상에 따로 새로 저장하기 때문이다
위 예제의 부분2
System.out.println(str1.toUpperCase());
- 한번 대문자로 출력한 후 참조하는 방법이 없으므로 없어짐(그림 3번 표시)
- 이 이후 str1을 출력시 다시 Java Programming으로 나옴
변경된 값 재사용
- str2처럼 이 바뀐 결과를 저장하는 새로 힙에 생긴 공간의 주솟값을 저장을 해야함(그림 4번 표시)
위 예제의 부분3
String str2=str1.toUpperCase(); //메소드의 처리 결과를 str2에 저장
System.out.println(str2);
- 이 str2가 새로바뀐 결과가 저장된 힙메모리의 공간을 받아서 주솟값을 저장해야만 재사용가능하고 str2를 통해 그 바뀐 결과를 출력 할 수 있다
- 즉 가리켜주는 객체 없으면 값이 사라짐 재사용되지 않는 힙메모리 값은 가비지콜렉터가 지움
그림
값이 변할때 메모리 처리
- String 객체를 생성한 후에 메소드에 의해서 값의 변화가 일어나면 변경된 값을 힙메모리 영역에 다시 저장 한다.
Garbage Collection 기능 (쓰레기 수집 기능)
- 재사용할 수 없는 힙메모리 영역의 데이터를 모아서 지워주는 기능
- 자동 메모리 관리 기능임
- 개발자가 메모리 관리 신경 크게 안써도 됨
+ StringBuffer 클래스
- 메모리상에 문자열 저장하는건 공통적이지만 String과 달리 새로운 공간에 저장하진 않는다
변경된 값을 재사용하기
String original = "Java Programming"
String lowerCase = original.toLowerCase(); //java programming
String upperCase = original.toUpperCase(); //JAVA PROGRAMMING
- String은 이렇게 변경된 값의 공간의 주소를 저장할 변수가 있어야 재사용 가능하다.
String 클래스 메소드
String클래스의 toUpperCase() 메소드
- 문자열을 대문자로 바꿔주는 메소드
String클래스의 toLowerCase() 메소드
- 문자열을 소문자로 바꿔주는 메소드
String클래스의 length() 메소드
- 한글이든 영문이든 몇글자인지를 구해준다.
- 한칸 비어있는 공백도 1글자로 인식함
- 문자열의 길이를 구해준다. 글자수를 구해줌
String클래스의 length() 메소드 예제
- FindBlankIndex.java
package p2022_07_01;
public class FindBlankIndex {
public static void main( String[] args ) {
String message = "Java program creates many objects.";
// message의 길이를 구함.
// length() : 문자열의 길이를 구해준다. 글자수를 구해줌
int len = message.length();
System.out.println(len); // len = 34;
// message 중에서 ' '을 찾음
for( int i=0 ; i<len ; i++ ) {
char c = message.charAt( i );
if( c == ' ' ) { //공백의 인덱스 번호를 구해서 출력
System.out.println( "index = " + i );
}
}//for end
}
}
- 공백이나 . 까지도 한글자로 포함
- 반환형 int, 문자열의 길이를 리턴
- for문으로 루프 돌려서 0부터 len보다 작을때까지 즉 len 만큼 for문을 돌림
length vs length() vs size()
- 배열의 크기를 구해주는 length 속성 -> 속성이므로 ()가 없다
- String 자료가 몇글자인지 구해주는 length() 메소드 -> 메소드이므로 ()
- 자료구조에 저장된 원소의 개수를 구해주는 size() 메소드 -> 메소드이므로 ()
String클래스의 중 charAt() 메소드
- 매개변수 int 이고 안에 인덱스 번호가 들어감
- 리턴형은 char임 즉 인덱스를 받아서 거기에 해당하는 문자를 가져옴.
- 인덱스는 0번부터 시작
그림
String클래스의 중 charAt() 메소드 예제
package p2022_07_01;
public class FindBlankIndex {
public static void main(String[] args) {
String message = "Java program creates many objects.";
// message의 길이를 구함.
// length() : 문자열의 길이를 구해준다. 글자수를 구해줌
int len = message.length();
System.out.println(len); // len = 34;
// message 중에서 ' '을 찾음
for (int i = 0; i < len; i++) {
char c = message.charAt(i);
if (c == ' ') { // 공백의 인덱스 번호를 구해서 출력
System.out.println("index = " + i);
}
} // for end
}
}
34
index = 4
index = 12
index = 20
index = 25
- ' ' 즉 공백이 인덱스 몇변이 있는지 출력해줌 (공백을 찾아주는 코드)
String클래스의 indexOf() 메소드
- charAt과 반대기능의 메소드
- 특정 문자의 인덱스번호를 구해주는 메소드
- 찾고자하는 문자가 없을때는 -1을 리턴함
- API 문서에서 indexOf() 메소드 찾아보면 메소드 오버로딩 되어있다
String클래스의 indexOf() 메소드 예제1
String message = "Java program creates many objects.";
int index1 = message.indexOf( 'a' );
- 출력 : 1
- a란 문자의 index 번호를 구해와라
- a가 여러개 있을땐, 가장 먼저 나오는 a의 인덱스 번호를 구해라
String클래스의 indexOf() 메소드 예제2
String message = "Java program creates many objects.";
int index2 = message.indexOf( 97 );
- 출력 : 1
- 97은 10진수 아스키 코드값이므로 거기에 해당하는 영문자를 찾아줌
- 이 영문자를 찾아서 인덱스를 가져와줌
- 10진수 아스키코드(97) 에 해당되는 문자('a')의 인덱스 번호를 구함.
- 이 97을 65로 바꾸면? -> 'A'를 찾는데 찾고자하는 문자가 없으므로 -1을 리턴함
String클래스의 indexOf() 메소드 예제3(매개변수가 2개)
String message = "Java program creates many objects.";
//index번호 13번째 이후에서 'a'의 인덱스 번호를 구함
int index3 = message.indexOf( 'a', 13 );
System.out.println( index3 );
- index번호가 13번 이후에 가장 먼저나오는 'a' 의 인덱스 번호를 찾아라
- 즉 c(13) 부터 찾아라 그 'a' 는 16이 나옴
- 이렇게 위치가 지정될땐 그 이후의 문자를 찾고 위치 지정이 안되었을떈 아까의 예시처럼 가장 먼저나오는 문자의 인덱스값을 찾음
String클래스의 indexOf() 메소드 예제4(매개변수가 String)
String message = "Java program creates many objects.";
// 가장 먼저 나오는 'av'의 인덱스 번호를 구함
int index4 = message.indexOf( "av" );
System.out.println( index4 );
- 출력 : 1
- Java의 av 이므로 결과는 1
- 문자 한글자가 아니라 문자열이 들어가는 경우임
- 가장 먼저 나오는 av의 인덱스 번호를 구해라
String클래스의 indexOf() 메소드 예제5(매개변수가 2개)
String message = "Java program creates many objects.";
// index번호 12번 이후에 나오는 'man'의 인덱스 번호를 구함
int index5 = message.indexOf( "man", 12 );
System.out.println( index5 );
- 이렇게 위치가 지정될땐 그 이후의 문자열의 인덱스번호를 주고 위치 지정이 안되었을떈 아까의 예시처럼 가장 먼저나오는 문자의 인덱스값을 찾음
String클래스의 indexOf() 메소드 예제6(결과가 없는 경우)
String message = "Java program creates many objects.";
// 찾는 문자가 없는 경우에는 -1을 리턴한다.
int index6 = message.indexOf( "java" );
System.out.println( index6 );
- 출력 : -1
- 소문자 java가 없다 찾고자하는 결과없으면 -1 리턴한다
- 이 indexOf 메소드는 대소문자를 구분한다
String클래스의 trim() 메소드
- 문좌열 좌,우의 공백을 없애주는 역할
String클래스의 equals() 메소드
- boolean equals()
- 값을 비교하는 역할
- 가리키는 값들끼리 비교함
String클래스의 trim() 메소드 / equals() 메소드 예제
package p2022_07_01;
public class TrimTest {
public static void main( String[] args ) {
// trim() : 문좌열 좌.우의 공백을 없애주는 역할
// boolean equals() : 값을 비교하는 역할
String str1 = new String( "gemini " );
String str2 = new String( " gemini " );
System.out.println( str1.equals( str2 ));
System.out.println( str1.trim().equals( str2.trim()));
}
}
- str1 가 가리키는 gemini 문자열 오른쪽에 공백이 있다
- str2 가 가리키는 gemini 문자열 왼쪽에 공백이있다
- 공백도 메모리상에 공간을 차지함
위 예제 부분1
System.out.println( str1.equals( str2 )); //false
- 공백도 문자로 인식하므로 서로 다른 값으로 인식함.
위 예제 부분2
System.out.println( str1.trim().equals( str2.trim()));
- 서로 같은값임.
- str1.trim()은 str1이 가리키는 문자열 오른쪽 공백 없애줌(좌,우 모두)
- str2.trim()은 str2이 가리키는 문자열 왼 공백 없애줌(좌,우 모두)
- 둘다 gemini만 남게되고 값이 같으므로 true리턴
String클래스의 replace() 메소드
- 문자열에서 첫번째 매개변수 값을 두번째 매개변수 값으로 변환시켜줌
ex) replace("자바","JAVA") : "자바"를 "JAVA"로 치환
String클래스의 replace() 메소드 예제1
- ReplaceEx.java
package p2022_07_01;
public class ReplaceEx {
public static void main(String[] args) {
//p506
//replace("자바","JAVA") : "자바"를 "JAVA"로 치환
String oldStr = "자바는 객체지향 언어 입니다.";
String newStr = oldStr.replace("자바", "JAVA");
System.out.println(oldStr);
System.out.println(newStr);
}
}
자바는 객체지향 언어 입니다.
JAVA는 객체지향 언어 입니다.
String클래스의 replace() 메소드 예제2
String oldStr = "자바는 객체지향 언어 입니다. 자바";
String newStr = oldStr.replace("자바", "JAVA");
System.out.println(oldStr);
System.out.println(newStr);
자바는 객체지향 언어 입니다.
자바 JAVA는 객체지향 언어 입니다.JAVA
- "자바" 가 여러개 있어도 다 JAVA로 바꿈
+ String클래스는 메소드를 통해 값의 변화가 일어나면 매번 힙메모리상의 새로운공간에 바뀐값을저장함
String클래스의 substring() 메소드
- 일부 문자열만 추출
- 메소드 오버로딩되어있다
- 매개변수가 2개인 경우, 매개변수가 1개인 경우 추출하는 범위가 달라진다.
1. 매개변수 2개인경우
- 시작과 끝 인덱스를 지정한다
- 하지만 실제 우리가 추출하는건 하나 적게 추출함 즉 begInindex ~ endIndex-1까지 추출
2. 매개변수 1개인경우
- 시작 인덱스만 지정한다
- 시작 인덱스로부터 끝까지 추출하라는 의미
String클래스의 substring() 메소드 정리
- substring() : 전체 문자열에서 특정 범위의 문자를 추출하는 역할
- substring(n) : index번호 n번 부터 끝까지 추출
- substring(n1, n2) : index번호 n1번 부터 (n2-1)번 까지 추출
String클래스의 substring() 메소드 예제1(매개변수 1개)
String message = "Java program creates many objects.";
// 인덱스번호 13번 부터 끝까지 추출
String str1 = message.substring( 13 );
System.out.println( str1 );
creates many objects.
- c가 13번 위치였다. 즉 13부터 모두 추출
- 13은 인덱스 번호 13번부터 끝까지 추출해서 결과를 str1 변수에 저장하고 출력시켜라는 의미
String클래스의 substring() 메소드 예제2(매개변수2개)
String message = "Java program creates many objects.";
// 인덱스번호 13번 부터 15번까지 추출
String str2 = message.substring( 13, 16 );
System.out.println( str2 );
cre
- c는 13, r은 14, e는 15 (15까지 추출)
- beginIndexNum이 13번 endIndexNum이 16인데 실제로는 13부터 15번까지 추출함
- 여기서 str1과 str2는 변경된 문자열을 가리킴(저장)
- 자바는 substring 메소드만 제공함
String클래스의 substring() 메소드 예제3
- SubstringEx.java
- substring() 이용해서 한글자 추출하기
- substring(그 글자 인덱스, 그 다음글자 인덱스)
+ string값 비교에 == 쓰지말고 equals쓰기
package p2022_07_01;
public class SubstringEx {
public static void main(String[] args) {
//아래와 같이 주민번호가 있을때, 남자인지 여자인지 판별하는 프로그램을 작성하세요?
String jumin = "900101-2233456"; // 2000년 이후 남자는 3번, 여자는 4번
String gender = jumin.substring(7, 8);
if (gender.equals("1") || gender.equals("3")) {
System.out.println("남자");
} else if (gender.equals("2") || gender.equals("4")) {
System.out.println("여자");
}
}
}
- 문자끼리 비교하는거니 gender.equals("1") 라고 "1"이라고 문자를 넣어야지 숫자 1을 넣으면 안됨!
- if-else로 해도 되지만 주민번호 첫자리 수 5(귀화한분들) 이런 경우도 있으므로 안전상 if-elseif로 해야한다
위 예제 부분1
String gender = jumin.substring(7, 8);
- 이렇게 해야 7번 인덱스의 문자열을 가져옴
String클래스의 substring() 메소드 예제4
- 키보드로 주민번호를 입력받는다, 주민번호 문자로 받아야함(문자열 클래스로 이것저것 할 것 이므로)
- 앞자리 6자리가아니면 메세지 뿌림
- 뒷자리 7자리가아니면 메세지 뿌림
- 이런걸 유효성 검사라고 한다
- 그리고 이 모든게 완벽한 값이면 입력한 주민번호가 남자인지 여자인지도 판별
package p2022_07_01;
import java.util.Scanner;
public class JuminCheck {
public static void main(String[] args) {
// 키보드로 주민번호를 입력 받아서 남자인지 여자인지를 판별하는 프로그램을 작성하세요?
// 단, 주민번호 앞자리는 6자리, 뒷자리는 7자리 인지를 유효성 검사를 한다.
// 키보드로 주민번호 입력받기
Scanner sc = new Scanner(System.in);
System.out.println("주민번호 앞자리를 입력 하세요?");
String jumin1 = sc.nextLine();
System.out.println("주민번호 뒷자리를 입력 하세요?");
String jumin2 = sc.nextLine();
// 남녀
String g = jumin2.substring(0, 1); // 0번 인덱스 추출한다는 의미
// 유효성 검사 & gender
if (jumin1.length() != 6) {
System.out.println("주민번호 앞자리 6자리를 입력하세요.");
} else if (jumin2.length() != 7) {
System.out.println("주민번호 뒷자리 7자리를 입력하세요.");
} else if (g.equals("1") || g.equals("3")) {
System.out.println("남자");
} else if (g.equals("2") || g.equals("4")) {
System.out.println("여자");
} else {
System.out.println("똑바로 입력 하세요.");
}
}
}
- if-elseif-else문 처리기때문에 처음 주민번호 앞자리 6자리가 아니면 더이상 아래쪽을 실행안함.
- 주민번호 앞자리 6자리인데 뒷자리 7자리 아니면 두번째에 걸림 아래 실행 안함
- 둘다 개수가 맞으면 이제야 남/녀 검사를함
- 주민번호는 6,7 다 맞는데 뒷자리 첫번째가 1234가 아니면 마지막인 else 구문에서 걸린다
+ String클래스의 split() 메소드
- 이후 뒤에서 자세히 설명함(StringTokenizer 클래스 공부 이후)
- 전체 문자에서 구분기호를 가지고 문자를 추출할때 사용함
- @ 나 / 등의 정규 표현식을 구분자로 해서 문자를 자름 이걸 파싱이라고함
- 결과를 돌려주는 자료형은 String형 1차원 배열로 돌려줌
+ Strping클래스의 split() 메소드는 은 StringTokenizer 와 비슷한 역할을 하지만 더 쓰기 편하다
+ String클래스의 split() 메소드 오버라이딩
- split(String regex)
- split(String regex, int limit)
String 클래스와 메모리 정리
- String 클래스는 메소드에서 값의 변화가 일어나면 변경된 값을 힙 메모리에 매번 새로운공간을 만들어서 사용함
- 재사용은 값을 받아주는 변수가 있을때만 사용가능하고 변경된정보에 접근이 불가능하면 가비지 콜렉터가 지움
사용빈도
String >>> StringTokenizer >>>>> StringBuffer
String, StringTokenzier, StringBuffer
- 공통적 특징 : 힙메모리상에 문자를 저장함
- 하지만 메모리상에 데이터를 처리하는부분이 다름 (메모리상에 문자를 저장하는 방식이 다름)
- String : 메소드에서 값의 변화가 일어나면 변경된 값을 힙 메모리에 매번 새로운공간을 만들어서 사용함
- StringBuffer : 버퍼라는 기억장소를 쓰기때문에 값의 변화가 일어나더라도 새로운 공간에 값을 저장하지 않음. 시작 주소값이 바뀌지 않음. 값을 계속 누적하는 경우에 이 클래스 쓰는 경우가 있다
StringBuffer
- 사용빈도 낮음
- StringBuilder 와 비슷한 기능(이건 안함)
- StringBuffer도 java.lang에 있어서 import 안해도 됨
- Buffer라는 임시 기억공간에 문자열을 저장함, 기능적으로 String과 다르다
StringBuffer 생성자
- 매개변수가 int capacity로 된 생상자가 있다, 버퍼라는 임시기억장소의 크기를 생성하는 거임
- 크기를 지정하면 지정된크기로 만들어줌, 크기 설정 따로 안해도 버퍼라는 임시기억소 만듬
- 설정안하면 기본적으로 16characther임 16글자 저장하기위한 힙메모리상의 공간을 만들어줌
StringBuffer 예제
- StringBufferTest.java
package p2022_07_01;
public class StringBufferTest {
public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer("gemini");
System.out.println("sb1.length() : " + sb1.length()); //6
System.out.println("sb1.capacity() : " + sb1.capacity()); //22
sb1.append("A string buffer implements" + "a mutable sequence of characters");
System.out.println("sb1.length() : " + sb1.length()); //64
System.out.println("sb1.capacity() : " + sb1.capacity()); //64
StringBuffer sb2 = new StringBuffer();
System.out.println("sb2.length() : " + sb2.length()); //0
System.out.println("sb2.capacity() : " + sb2.capacity()); //16
}
}
위 예제 부분1(매개변수가 있는 생성자)
StringBuffer sb1 = new StringBuffer("gemini");
- 매개변수가 있는 생성자로 객체를 생성하고 있다
- "gemini"가 힙메모리 상에 저장되고, sb1이 이 주소를 갖고 있다.
- length()메소드 지원 : 문자열길이를 구해줌
- capacity() 메소드 : 힙메모리상의 할당된 바이트 크기 알려줌 //22바이트
- append() 메소드 : 문자열을 추가함
- 동적으로 공간을 늘려주는 기능도 있다 자동으로 늘려줌
- 만약 22보다 큰 크기의 문자열을 넣으면 동적으로 공간을 늘려줌
- 다시 length()를 구했을때 64가 나옴
- 처음에 22바이트였던 공간을 64만큼 늘려줌
위 예제 부분2(기본생성자)
StringBuffer sb2 = new StringBuffer();
- 기본생성자로 객체를 생성하고 있다
- 길이 length 는 0임
- 자동으로 16바이트(16글자공간 만들어줌) 로 만들어줌
- 아무것도 안가리키기 때문에 length()는 0
StringBuffer와 값의 변화
- StringBuffer는 값의 변화가 일어나더라도 시작주소값이 바뀌지 않는다
- String과 다른 특징
StringBuffer와 값의 변화 예제
- AppendStringBuffer.java
package p2022_07_01;
public class AppendStringBuffer {
public static void main( String[] args ) {
// StringBuffer 객체 생성
StringBuffer sb1 = new StringBuffer( "gemini" );
System.out.println( "sb1 = " + sb1 );
// StringBuffer sb1에 문자열을 추가해 새로운 객체 생성
StringBuffer sb2 = sb1.append( " is beautiful" );
System.out.println( "sb2 = " + sb2 );
System.out.println( "sb1 = " + sb1 );
if(sb1 == sb2) {
System.out.println("같은 주소"); //같은 주소
}else {
System.out.println("다른 주소");
}
// 정수형 데이타 형을 추가
System.out.println( sb1.append( 1004 ));
System.out.println( "sb1 = " + sb1 );
System.out.println( "sb2 = " + sb2 );
String str = new String(sb1); // StringBuffer를 String으로 변환
System.out.println(str.toUpperCase());
}
}
sb1 = gemini
sb2 = gemini is beautiful
sb1 = gemini is beautiful
같은 주소
gemini is beautiful1004
sb1 = gemini is beautiful1004
sb2 = gemini is beautiful1004
GEMINI IS BEAUTIFUL1004
위 예제 부분1
// StringBuffer 객체 생성
StringBuffer sb1 = new StringBuffer( "gemini" );
System.out.println( "sb1 = " + sb1 );
- 힙메모리상에 "gemini"라는 값이 저장되고 그걸 sb1이 시작주소를 가지고 있다
위 예제 부분2
// StringBuffer sb1에 문자열을 추가해 새로운 객체 생성
StringBuffer sb2 = sb1.append( " is beautiful" );
System.out.println( "sb2 = " + sb2 );
System.out.println( "sb1 = " + sb1 );
- append() 함수 : 기존 문자열에 새로운 문자열을 이어 붙여줌 (String클래스엔 이 함수 지원안됨)
- 그리고 이걸 sb2가 주소를 가지게 함
위 예제 부분3
if(sb1 == sb2) {
System.out.println("같은 주소"); //같은 주소
}else {
System.out.println("다른 주소");
}
- 출력 : 같은 주소
- 문자열이 변경되었지만 새로운 힙공간에 저장하지 않음 그러니 sb1과 sb2가 가리키는건 같음!
- 둘다 같은 문자열이 출력됨
- 즉 같은 주소, 같은 값 같은걸 가리키고 있음
그림
String vs StringBuffer 차이 정리
- String : 값의 변화 일어나면 새로운 공간에 그 결과 저장. 원래 값의 주솟값 != 바뀐 값의 주솟값
- StringBuffer : 값의 변화 일어나도 기존 공간에 적용, 변경된 값의 시작주솟값이 바뀌지 않음
위 예제 부분4
// 정수형 데이타 형을 추가
System.out.println( sb1.append( 1004 ));
System.out.println( "sb1 = " + sb1 );
System.out.println( "sb2 = " + sb2 );
String str = new String(sb1); // StringBuffer를 String으로 변환
System.out.println(str.toUpperCase());
- sb1에 append(1004) 함
- 그 후에 sb1출력하나 sb2 출력하나 같은 gemini is beautiful1004 가 출력됨
- 같은주소를 리턴받았었기때문에 그렇다
StringBuffer로 저장된 문자열을 대문자로 바꾸기
- StringBuffer 클래스는 toUperCase() 메소드가 없어서 못쓴다 (langth()는 있음)
- String과 StringBuffer 사이는 상속관계 없으므로 String 클래스 안에 있는걸 StringBuffer가 상속받아 쓸수도 없음
-> String 클래스의 생성자를 활용해서 대문자로 바꿔주면 된다.
-> String 클래스 생성자를 찾아보면 매개변수가 StringBuffer인 생성자가 있다
- String(StringBuffer buffer) 생성자
- 이 생성자를 통해서 StringBuffer -> String 으로 변환 가능
- String 객체로 받아서 toUpperCase 해서 대문자 변환하기
StringBuffer로 저장된 문자열을 대문자로 바꾸기 예제
- InsertStringBuffer.java
- StringBuffer 클래스의 append() 메소드 : 기존 문자열에 끝 추가
- StringBuffer 클래스의 insert() 메소드 : 지정된 특정 위치에 문자열을 삽입 시킴
package p2022_07_01;
public class InsertStringBuffer {
public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer("gemini is beautiful");
System.out.println(sb1);
// 인덱스 10번 위치에 very 문자를 삽입
sb1.insert(10, "very");
System.out.println(sb1);
// 인덱스 0번 위치에 1004 를 삽입하라(숫자로 써도 문자가됨)
sb1.insert(0, 1004);
System.out.println(sb1);
}
}
gemini is beautiful
gemini is verybeautiful
1004gemini is verybeautiful
- 처음엔 인덱스 10번위치에 "very"란 문자열을 삽입시켜라는 의미
- is beautiful 사이의 공백이 인덱스 10이다. 그 10번 뒤에 삽입 됨-> is verybeautiful
- 이후 인덱스 0번위치에 1004를 삽입하라는 의미
StringBuffer 클래스의 사용
- 문자열 처리 보통은 String 클래스로 다 처리가능함
- 값을 계속 누적시키거나 하는 특별한 경우들에만 StringBuffer를 사용함
+ 문자열 분리 방법 2가지
- 구분기호를 가지고 문자를 추출하는, 잘라서 토큰으로 추출하는 역할
1. java.util.StringTokenizer이용
2. String의 split() 메소드 활용
StringTokenizer 클래스
- 앞의 두 클래스와 기능이 좀 다름
- 특정 문자를 구분기호를 가지고 토큰을 구해오는 역할을 함
- 문자를 파싱해서 처리해주는 역할을 한다
- java.util 안에 있다
StringTokenizer 클래스 생성자
- 매개변수 1,2,3개인 3개의 생성자 중 StringTokenizer(String str, String delim) 을 주로 사용한다
- 첫번째 매개변수에는 전체 문자열 또는 그 문자열을 담은 변수명이 온다
- 두번째 매개변수에는 구분기호가들어간다, 구분기호는 @ # / 등이 될 수 있다.
StringTokenizer 클래스 예제1
- StringTest04.java
package p2022_07_01;
import java.util.*;
class StringTest04 {
public static void main(String[] args) {
StringTokenizer str = new StringTokenizer("이순신#을지문덕#강감찬#광개토대왕", "#");
// System.out.println(str.nextToken());
// System.out.println(str.nextToken());
// System.out.println(str.nextToken());
// System.out.println(str.nextToken());
// System.out.println(str.nextToken()); // 예외발생
// 파싱된 문자열이 모두 몇 개인지 되는지 알려줌
int cnt = str.countTokens();
System.out.println("파싱할 문자열의 총갯수-> " + cnt);
// System.out.println(str.nextToken());
while (str.hasMoreTokens()) { // 토큰이 있으면
System.out.print(str.nextToken() + "\t");// 차례대로 파싱된 문자열을 얻어온다.
}
} // main() end
}
StringTokenizer 클래스 사용예시(위 예제 부분1)
StringTokenizer str = new StringTokenizer("이순신#을지문덕#강감찬#광개토대왕", "#");
- 이렇게 쓰고 두번째 자리에는 구분기호가 들어감
- 이 #으로 전체문자열을 파싱 = 자른다
- 파싱을 하고 리턴되는 "이순신" "을지문덕" 등을 토큰이라고함
- nextTokens() 메소드 : 이 토큰들을 구해오는 메소드
System.out.println(str.nextToken());
- 하면 첫번쨰 토큰인 이순신 이 출력됨
System.out.println(str.nextToken());
System.out.println(str.nextToken());
- 이렇게 더 하면 이순신, 을지문덕 출력됨
- nextToken()메소드는 String형으로 리턴한다
StringTokenizer str = new StringTokenizer("이순신#을지문덕#강감찬#광개토대왕", "#");
System.out.println(str.nextToken());
System.out.println(str.nextToken());
System.out.println(str.nextToken());
System.out.println(str.nextToken());
이순신
을지문덕
강감찬
광개토대왕
- 가져올토큰 없는데 한번 더 nextToken() 메소드를 쓰면?
- 예외가 발생해서 프로그램이 비정상적으로 멈추게됨
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at p2022_07_01.StringTest04.main(StringTest04.java:14)
- NoSuchElementException 예외 발생
* 예외 : 예상하지못했던 프로그램상 오류
-> 가져올 토큰이 있는지 없는지 판별을 해야함
가져올 토큰이 있는지 판별(위 예제 부분2)
- 가져올 토큰이있는경우에만 출력하기
// 파싱된 문자열이 모두 몇 개인지 되는지 알려줌
int cnt = str.countTokens();
System.out.println("파싱할 문자열의 총갯수-> " + cnt); //4출력
- 토큰들 : 잘려진 부분들
- countTokens() 메소드 : 토큰의 개수를 구해주는 메소드
- 토큰이있을때만 가져오기위해서 처리하기 아래에
while (str.hasMoreTokens()) { // 토큰이 있으면
System.out.print(str.nextToken() + "\t");// 차례대로 파싱된 문자열을 얻어온다.
}
이순신 을지문덕 강감찬 광개토대왕
- hasMoreTokens() 메소드 : 가져올 토큰이 있는지 없는지 판별하는 역할을 함
- 결과를 돌려주는 리턴자료형은 boolean, 가져올 토큰 있으면 true,없으면 false 리턴해서 while문 제어
-> 이러면 예외가 발생할 가능성이 없다
nextTokens()의 특징(위 예제 부분3)
System.out.println(str.nextToken());
while (str.hasMoreTokens()) { // 토큰이 있으면
System.out.print(str.nextToken() + "\t");// 차례대로 파싱된 문자열을 얻어온다.
}
- 이순신을 위에서 부르고 while문 에서는 을지문덕 감감찬 광개토대왕 만 나옴
- 한번 nextToken()쓰면 그건 끝난것, 그 뒤부터 출력됨
+ String 클래스의 split() 메소드가 이와 비슷한 역할을 한다.
StringTokenizer 클래스 예제2
- StringTokenizerTest1.java
package p2022_07_01;
import java.util.StringTokenizer;
public class StringTokenizerTest1 {
public static void main(String[] args) {
String source1="111-111|강원도|춘천시|퇴계동";
StringTokenizer st1=new StringTokenizer(source1,"|");
String zip=st1.nextToken();
String dou=st1.nextToken();
String si=st1.nextToken();
String dong=st1.nextToken();
System.out.println("우편번호:" +zip);
System.out.println("도:" +dou);
System.out.println("시:" +si);
System.out.println("동:" +dong);
}
}
우편번호:111-111
도:강원도
시:춘천시
동:퇴계동
- String 객체 source1에 문자열들이 있다
- - StringTokenzier 는 구분기호를 1개밖에 쓰지 못한다!
- "-" 같은거까지 더 구분 못함
- split()은 여러개 구분기호로 파싱 가능
- nextToken() 의 리턴형은 String
- nextToken() 으로 토큰 구해와서 String 객체에 저장했다.
StringTokenizer 클래스 예제3(매개변수가 3개)
- StringTokenizerTest2.java
package p2022_07_01;
import java.util.StringTokenizer;
public class StringTokenizerTest2 {
public static void main(String[] args) {
String source1 = "한국 미국 태국 중국 이란";
StringTokenizer st1 = new StringTokenizer(source1, " ");
while (st1.hasMoreTokens()) {
System.out.println("st1.token:" + st1.nextToken());
}
System.out.println();
System.out.println();
String source2 = "푸들,삽살개,풍산개,진돗개";
StringTokenizer st2 = new StringTokenizer(source2, ",");
while (st2.hasMoreTokens()) {
System.out.println("st2.token:" + st2.nextToken());
}
System.out.println();
System.out.println();
// true : 구분기후(,)를 토큰으로 처리해준다.
StringTokenizer st3 = new StringTokenizer(source2, ",", true);
while (st3.hasMoreTokens()) {
System.out.println("st3.token:" + st3.nextToken());
}
}
}
위 예제 부분1
String source1="한국 미국 태국 중국 이란";
StringTokenizer st1=new StringTokenizer(source1," ");
- 국가명 사이에 공백이 들어가있으니 공백으로 파싱하자
- 첫번째 매개변수에는 문자열 또는 문자열이 저장된 변수가 들어간다
- 두번쨰 매개변수에는 구분기호가 들어가는데 여기선 " " 공백으로 파싱
위 예제 부분2
while(st1.hasMoreTokens()){
System.out.println("st1.token:"+st1.nextToken());
}
- hasMoreTokens() : 가져올 토큰이 있는지 판별
- while문 안에 가져올 토큰이있을때만 true를 리턴해서 while문 돌려서 모두 출력함
- 가져올 토큰이 없으면 false리턴
위 예제 부분3
String source2="푸들,삽살개,풍산개,진돗개";
StringTokenizer st2=new StringTokenizer(source2,",");
while(st2.hasMoreTokens()){
System.out.println("st2.token:"+st2.nextToken());
}
매개변수 3개인 StringTokenizer(위 예제 부분4)
//true : 구분기후(,)를 토큰으로 처리해준다.
StringTokenizer st3=new StringTokenizer(source2,",",true);
while(st3.hasMoreTokens()){
System.out.println("st3.token:"+st3.nextToken());
}
st3.token:푸들
st3.token:,
st3.token:삽살개
st3.token:,
st3.token:풍산개
st3.token:,
st3.token:진돗개
- 첫번째, 두번쨰 매개변수에 넣어야하는건 위와 같다
- 하지만 3번째 매개변수가 boolean형이다 즉 true나 false값을 써야함
- 세번째 매개변수에 true가 오면, 그 구분기호도 파싱될 토큰으로 처리하라는 의미
- 그래서 여기는 , 도 토큰기호로 인식해서 nextToken()하면 푸들 다음의 토큰으로 , 라는 토큰이옴
- false넣으면 다른 위의 예제들과 같게 구분기호는 토큰으로 인식 안함.
String클래스의 split() 메소드
- StringTokenzier과 비슷한 역할하는 "메소드"
- 기능적으로 보면 split()이 쓰기가 더 편하고 여러개의 구분기호 가지고 있어도 파싱 가능함
- String[] Split(String regex)
- 이 매개변수에 구분기호가 온다
- 이 파싱된 결과를 왼쪽의 String 1차열 배열로 리턴
- 첫번째 토큰은 0번방, 두번째 토큰은 1번방, 세번째 토큰은 2번방...
String클래스의 split() 메소드 예시1
- 주민번호앞자리-주민번호뒷자리 를 - 로 파싱하자
String jumin = "900101-1234567";
String[] j = jumin.split("-");
- 구분기호를가지고 잘라서 결과를 왼쪽의 j (String형 배열) 로 전달
- "900101"인 첫번째 토큰이 j[0], "1234567" 인 두번째 토큰은 j[1]로 들어감
String클래스의 split() 메소드 예제1
- SplitEx.java
package p2022_07_01;
public class SplitEx {
public static void main(String[] args) {
// String[] split(String regex) 메소드
String jumin = "900101-1234567";
String[] j = jumin.split("-");
System.out.println("주민번호 앞자리 : " + j[0]);
System.out.println("주민번호 앞자리 : " + j[1]);
for (int i = 0; i < j.length; i++) { //향상된for문
System.out.println("주민번호 " + j[i]);
}
}
}
주민번호 앞자리 900101
주민번호 뒷자리 1234567
주민번호 900101
주민번호 1234567
900101
1234567
+ 나중에 배열의 크기를 잘 모르는 경우에 length속성을 꼭 써야한다
String클래스의 split() 메소드 예제2
String tel = "010-1234-5678";
String[] t = tel.split("-");
for (int i = 0; i < t.length; i++) {
System.out.println(t[i]);
}
010
1234
5678
String클래스의 split() 메소드 예제3
// @를 구분기호로 아이디명과 도메인명 파싱하기
String email = "totoro@naver.com"; //정해진 형식이 있다.
String[] e = email.split("@");
System.out.println("아이디 : " + e[0]);
System.out.println("도메인 : " + e[1]);
아이디 : totoro
도메인 : naver.com
구분기호 여러개로 파싱하기(split() 메소드 예제4)
- 구분기호 여러개 섞여있어도 파싱하는게 가능하다
String[] names = text.split("$|,|-");
- 구분기호를 연결해서서 | (파이퍼) 로 연결하면 또는 이런 구분기호들을 이용해 파싱하겠다는 의미
- 이런건 StringTokenizer 가 지원하지 못하는 기능임
- SplitEx1.java
package p2022_07_01;
public class SplitEx1 {
public static void main(String[] args) {
// p512
// String[] split(String regex); 메소드
String text = "홍길동&이수홍,박연수,김자바-최명호";
String[] names = text.split("&|,|-");
// for (int i = 0; i < names.length; i++) {
// System.out.println(names[i]);
// }
// System.out.println();
for(String name : names) {
System.out.println(name);
} //향상된for문
}
}
홍길동
이수홍
박연수
김자바
최명호
+ | 는 구분기호로 쑬 수 없다
문자열 파싱하는 방법 정리
1. StringTokenizer 클래스
2. String의 split() 메소드
'국비지원 과정 > JAVA' 카테고리의 다른 글
코딩 11일 / 2022.07.05 / JAVA의 상속2, 메소드 오버라이딩, 추상클래스1 (0) | 2022.07.13 |
---|---|
코딩 10일 / 2022.07.04 / JAVA의 Wrapper 클래스, 박싱, 언박싱, 업캐스팅, 다운캐스팅, 상속1 (0) | 2022.07.12 |
코딩 8일 / 2022.06.30 / JAVA의 싱글톤, final, 날짜시간 관련 클래스 (0) | 2022.07.07 |
코딩 7일 / 2022.06.29 / JAVA의 접근제어자,메소드 오버로딩,정적 변수,정적 메소드 (0) | 2022.07.05 |
코딩 6일 / 2022.06.28 / JAVA의 클래스,객체,필드,생성자 (0) | 2022.07.01 |