Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 2024 정보처리기사 시나공 필기
- jpa 활용2 - api 개발 고급
- 자바의 정석 기초편 ch1
- 자바의 정석 기초편 ch8
- 자바의 정석 기초편 ch7
- 자바의 정석 기초편 ch9
- jpa - 객체지향 쿼리 언어
- 2024 정보처리기사 수제비 실기
- 스프링 mvc2 - 타임리프
- 스프링 db1 - 스프링과 문제 해결
- 자바의 정석 기초편 ch3
- 스프링 입문(무료)
- 자바의 정석 기초편 ch11
- 게시글 목록 api
- 스프링 mvc2 - 로그인 처리
- 스프링 고급 - 스프링 aop
- @Aspect
- 스프링 mvc1 - 스프링 mvc
- 자바의 정석 기초편 ch5
- 자바의 정석 기초편 ch4
- 타임리프 - 기본기능
- 자바의 정석 기초편 ch14
- 자바의 정석 기초편 ch2
- 자바의 정석 기초편 ch13
- 자바의 정석 기초편 ch12
- 자바의 정석 기초편 ch6
- 스프링 db2 - 데이터 접근 기술
- 스프링 mvc2 - 검증
- 스프링 mvc1 - 서블릿
- 코드로 시작하는 자바 첫걸음
Archives
- Today
- Total
나구리의 개발공부기록
자바의 정석 기초편 ch9 - 7 ~ 11[String클래스, 문자열 비교, 빈 문자열, String클래스의 생성자와 메서드] 본문
유튜브 공부/JAVA의 정석 기초편(유튜브)
자바의 정석 기초편 ch9 - 7 ~ 11[String클래스, 문자열 비교, 빈 문자열, String클래스의 생성자와 메서드]
소소한나구리 2023. 12. 6. 13:391) String클래스
(1) 구성
- char[] (문자타입 배열)
- 메서드(문자열 관련)
// String 클래스의 구조
public final class String implements java.io.Serializable, Comparable {
private char[] value;
...(이하 메서드들)
(2) 특징
- 내용을 변경할 수 없는 불변(immutable)클래스
- 덧셈 연산자를 이용한 문자열 결합은 성능이 떨어짐(객체가 계속 만들어짐) -> 여담이지만 slf4j로 로그 출력시 + 가아닌 ,로 문자열과 변수를 결합하는 이유가 있음
- 문자열의 결합이나 변경이 잦다면(반복문안에서 문자를 지속적으로 결합 등) 내용을 변경할 수 있는 StringBuffer를 사용하는 것을 권장
String a = "a";
String b = "b";
a = a+b; // 새로운 객체에 "ab"가 담김, 즉 새로운 객체의 새로운 참조값으로 변수 a에 저장됨
2) 문자열의 비교
(1) String str = "abc";와 String str = new String("abc"); 차이
- new 연산자를 이용하면 항상 새로운 인스턴스(객체)를 생성함 즉, 저장된 논리의 값이 같아도 별도의 객체로 생성했으므로 참조값이 다름
- 문자열은 어차피 내용변경이 불가능하므로 특별한 경우를 제외하고 new 이용하여 객체를 여러번 만들 필요가 없고 new로 생성하게되면 오히려 메모리만 낭비 됨
// 빈 문자열 객체를 1개만 만들고 str1,str2,str3의 참조변수가 1개의 객체를 가르킴
// 메모리 절약
String str1 = "";
String str2 = "";
String str3 = "";
// 빈 문자열 객체를 3개나 생성하여 메모리 낭비 -> 가급적 사용 X
String str1 = new String("");
String str2 = new String("");
String str3 = new String("");
(2) 문자열의 비교는 equals()를 사용
- 등가비교 연산자(==)를 활용하여 비교하면 참조값을 비교하게 되므로 상황에 따라 거짓이 나올 수 있음(new로 객체를 생성 후 그 참조값을 비교했을 때)
- String 클래스의 equals()는 이미 오버라이딩 되어 정의되어있으므로 참조값이 아닌 논리 값을 비교함
// 문자열 리터럴 생성
String str1 = "abc";
String str2 = "abc";
// new 연산자로 String 인스턴스(객체) 생성
String str3 = new String("abc");
String str4 = new String("abc");
// str1과 str2는 하나의 문자열(내용변경불가) 주소를 공유함
// str3과 str4는 각각의 객체가 생성 되었으므로 주소가 다름
str 1 == str2 // 등가비교연산자 비교(주소비교)
// 0x100 == 0x100 주소가 같으므로 true
str 3 == str4 // 등가비교연산자 비교(주소비교)
// 0x200 == 0x300 주소가 다르므로 false
// 그래서 문자열비교는 equals()를 써야함(오버라이딩 되어있음)
str1.equals(str2) // true
str3.equals(str4) // true
(3) 문자열 리터럴이 하나만 만들어 지는 이유
- 문자열 리터럴은 new String()처럼 객체를 생성하지 않아도 프로그램 실행시 자동으로 생성됨
- 별도의 constant pool에 저장하여 관리함(상수 저장소)
- 같은 내용의 문자열 리터럴은 1개만 만들어짐
- String클래스는 불변클래스이므로 내용이 변하지 않으니 여러 참조변수가 하나의 주소를 공유할 수 있음.
3) 빈 문자열("", empty string)
- 내용이 없는 문자열(크기가 0인 char형 배열을 저장하는 문자열)
- String str = ""; 처럼 초기화 할 수 있음
- 자바에서는 길이가 0인 배열을 모든 타입에서 생성할 수 있음
char[] chArr = new char[0]; // 길이가 0인 char배열
int[] iArr = {}; // 길이가 0인 int배열
(1) 배열길이가 0인 배열은 아무것도 저장 못하는데 언제 사용하는가?
- 기본값으로 초기화 하거나, 숫자를 문자로 바꿀 때 등에 사용
- 빈 문자열은 다른 타입과 + 연산하여 간편히 문자열타입으로 형변환 할 때도 사용함
//기본값 초기화
String s = null;
char c = '\u0000'; // \u0000은 유니코드의 첫번째 문자
//빈 문자열, 공백으로 기본값 초기화를 간편하게(좋은 코드)
String s = "";
char c = '';
4) String클래스의 생성자와 메서드
(1) 생성자
- String(String s)
- 주어진 문자열을 갖는 String 인스턴스를 생성
- 거의 사용안함
String s = new String("Hello");
결과
// s = "Hello"
- String(char[] value)
- 주어진 문자타입 배열(value)을 갖는 String인스턴스를 생성
- 문자배열을 문자열로 반환할 때 간혹 사용함
- 반대로 문자열을 문자 배열로 변환 할 경우 toCharArray() 메서드를 활용함
char[] c = {'H','e','l','l','o'}
String s = new String(c);
// 결과
// s = "Hello"
- String(StringBuffer buf)
- StringBuffer인스턴스가 갖고 있는 문자열(buf)과 같은 내용의 String인스턴스를 생성, 즉 StringBuffer를 String으로 변경
- StringBuffer(내용 변경 가능한 문자열 - 이후에 배움)
// StringBuffer의 참조변수 sb를 String타입의 참조변수 s에 초기화
StringBuffer sb = new StringBuffer("Hello");
String s = new String(sb);
// 결과
// s = "Hello"
(1) 메서드
- char charAt(int index)
- 지정된 위치(index)에 있는 문자 1개를 반환
- 반환타입이 문자 타입임
// 인덱스 번호는 0부터 시작, H = 0 ... o = 4
String s = "Hello";
String n = "0123456";
// 참조변수 s가 가르키는 문자열의 인덱스번호 1이 가르키는 문자열을 참조변수 c에 반환
char c = "s.charAt(1)";
참조변수 n이 가르키는 문자열의 인덱스번호 1이 가르키는 문자열을 참조변수 c2에 반환
char c2 = "n.charAt(1)";
// 결과
// c = 'e'
// c2 = '1'
- int compareTo(String str)
- 두개의 문자열(str)을 사전순서(Dictionary Order)로 비교하여 내용이 같으면 0을 반환(반환타입이 정수타입임)
- 왼쪽이 작으면 음수, 오른쪽이 작으면 양수를 반환함
- 비교할 문자열들의 첫번째 인덱스부터 순차적으로 비교하며 같으면 다음 인덱스로 넘어가서 비교하고 다르면 그둘의 아스키코드값만큼의 차이를 반환하고 남은 문자열의 비교는 하지 않음
- 즉 왼쪽 문자의 아스키코드값 - 오른쪽 문자의 아스키코드값 연산한 값을 반환하는 것
- 정렬할 때 사용 -> 11장에서 자세히 다룸
int i = "aaa".compareTo("aaa"); // 비교 문자열이 같음
int i2 = "aaa".compareTo("bbb"); // 왼쪽 문자열이 오른쪽보다 작음 -> 음수반환
int i3 = "bbb".compareTo("aaa"); // 오른쪽 문자열이 왼쪽보다 작음 -> 양수반환
// 결과
// i = 0
// i2 = -1
// i3 = 1
- String concat(String str)
- 기존 문자열 뒤에 인자값의 문자열을 붙힘
String s = "Hello";
String s2 = s.concat(" World");
// 결과
// s2 = "Hello World"
- boolean contains(CharSequence s)
- 인자값의 문자열이 비교 대상의 문자열에 포함되어있는지 검사하고 포함하면 true 아니면 false로 반환
- 0번 인덱스부터 순차적으로 검사
** CharSequence 인터페이스
- 서로 상속계층도가 다른(공통조상이 없음) CharBuffer, Segment, String, StringBuffer,StringBuilder 클래스들을 묶음
- 위의 클래스들은 char[](문자열배열)을 다룬다는 공통점이 있어 인터페이스로 새로운 관계를 맺었기 때문에 contains()메서드를 모두 사용할 수 있음
String s = "abcdefg";
boolean b = s.contains("bc"); // 문자열 bc가 있는지 검사
// 결과
// b = true
- boolean endsWith(String suffix)
- 비교 대상의 문자열이 인자의 문자열(suffix)로 끝나는지 검사 하고 맞으면 true 틀리면 false를 반환
- 0번 인덱스부터 순차적으로 검사
String file = "Hello.txt";
boolean b = file.endsWith("txt"); // 문자열 file이 txt문자열로 끝나는지 검사
// 결과
// b = true
- boolean startsWith(String prefix)
- 지정된 문자열(prefix)로 시작하는지 검사 맞으면 true 틀리면 false를 반환
- 0번 인덱스부터 순차적으로 검사
String s = "java.lang.Object";
boolean b = s.startsWith("java"); // 문자열 s가 java문자열로 시작하는지 검사
boolean b2 = s.startsWith("lang"); // 문자열 s가 lang문자열로 시작하는지 검사
// 결과
// b = true
// b2 = false
- boolean equals(Object obj)
- 비교대상의 문자열과 인자로 받은 문자열을 비교하고 받은 인자가 문자열이 아니거나 일치하지 않으면 false를 반환하고 정확히 일치하면 true를 반환
String s = "Hello";
boolean b = s.equals("Hello");
boolean b2 = s.equals("hello");
// 결과
// b = true
// b2 = false
- boolean equalsIgnoreCase(String str)
- 대소문자 구분없이 equals()와 동일한 기능을하는 메서드
코드
String s = "Hello";
boolean b = s.equalsIgnoreCase("Hello");
boolean b2 = s.equalsIgnoreCase("hello");
결과
b = true
b2 = true
- int indexOf(int ch)
- 검색할 문자열에 인자의 문자가 존재하는지 확인 하여 index번호를 반환
- 인데스 0번부터 비교하며 못찾으면 -1을 반환
코드
String s = "Hello";
int idx1 = s.indexOf('o'); // o가 몇번째 인덱스에 있는지 확인
int idx2 = s.indexOf('k'); // k가 몇번째 인덱스에 있는지 확인 -> 없음 -> -1반환
결과
idx1 = 4
idx2 = -1
- int indexOf(int ch, int pos)
- 인자를 2개를 입력하면 2번째 인자의 인덱스 위치부터 indexOf와 동일한 기능을 수행하고 결과를 반환
- 즉, 인자로 들어온 pos값의 인덱스 위치부터 문자열 끝까지 비교 (오른쪽으로 비교한다고 이해하면 됨)
String s = "Hello";
int idx1 = s.indexOf('e', 0); // e가 인덱스 0부터 몇번째 인덱스에 있는지 확인
int idx2 = s.indexOf('e', 2); // e가 인덱스 2부터 몇번째 인덱스에 있는지 확인 -> 없음 -> -1 반환
// 결과
// idx1 = 1
// idx2 = -1
- int indexOf(String str)
- 대상의 문자열과 인자로 입력된 문자열이 정확히 일치하는 첫 인덱스 위치의 번호를 반환
- 인덱스 0번부터 비교하고 못찾으면 -1을 반환
String s = "ABCDEFG";
int idx1 = s.indexOf("CD"); // CD가 문자열에 존재하는지 확인, 처음 확인된 인덱스 번호를 반환
// 결과
// idx1 = 2
- int lastIndexOf(int ch)
- indexOf()의 기능(인자가 정수타입)을 문자열 끝에서부터 비교하여 인덱스 번호를 반환
String s = "java.lang.Object";
int idx1 = s.lastIndexOf('.'); // 문자열 뒤에서부터 '.' 을 찾는 즉시 인덱스 번호를 반환
int idx2 = s.lastIndexOf('.'idx1 - 1); // idx1의 값(8)의 위치부터 다시 '.'을 찾고 인덱스 번호를 반환
// 결과
// idx1 = 9
// idx2 = 4
- int lastIndexOf(String str)
- indexOf()의 기능(인자가 문자열타입)을 문자열 끝에서부터 비교하고 인덱스 번호를 반환
- 비교는 뒤에서하지만 반환하는 인덱스 번호는 맨 앞의 번호를 반환
String s = "java.lang.java";
// java 문자열을 뒤에서부터 비교, java의 j가 일치한 인덱스 번호를 반환
int idx1 = s.lastIndexOf("java");
// idx1다음 인덱스위치부터 비교
int idx2 = s.lastIndexOf("java", idx1-1);
// 결과
// idx1 = 10
// idx2 = 0
- int length()
- 문자열의 길이를 반환
String s = "Hello";
int length = s.length();
// 결과
// length = 5
- String[] split(String regex)
- 문자열을 지정된 분리자(regex)로 나누어 문자열 배열에 담아 반환
- regex(정규식) - Regular Expression 규칙이 있는 식
- 꼭 정규식으로 표현해야하는 것은 아니고 간단히 분리하고자 하는 특정 단어나 기호로 적용하는 경우도 많음
- 반환타입이 스트링 배열이기 때문에 배열의 각 인덱스의 0번부터 분리된 문자열이 하나씩 저장됨
String animals = "dog,cat,bear";
String[] arr = animals.split(",");
// 결과
// arr[0] = "dog"
// arr[1] = "cat"
// arr[2] = "bear"
- String[] split(String regex, int limit)
- split()의 기능을 수행하는데, 두번째 인자의 갯수만큼만 분리
- 즉 분리할 수 있는 문자열이 더 존재해도 그 갯수만큼만 분리하고 남은 문자열은 그대로 배열에 저장됨
- limit의 인자값이 분리할 수 있는 갯수보다 크더라도 에러가 발생하지않고 분리할 수 있을만큼 분리하여 배열에 저장함
String animals = "dog,cat,bear";
// 문자','분할, limit값이 2이므로 2개로 분할
String[] arr = animals.split(",", 2);
// 결과
// arr[0] = "dog"
// arr[1] = "cat,bear"
- String substring(int begin)
- 인자값의 인덱스 위치부터 문자열 끝까지를 반환
- String substring(int begin, int end)
- 두번째 인자값이 주어지면 첫번째 인자값의 인덱스 위치부터 두번째 인자값의 -1 인덱스 위치까지 반환
- 다만 두번째 인자값이 문자열의 길이(마지막 인덱스 번호)와 일치하면 해당 위치의 값도 적용되어 끝까지 반환함
- 마지막 인자값의 위치의 인덱스이 문자열의 길이와 일치하지 않으면 적용대상에 포함하지 않는 것에 주의 -> 2024년도 2회차 정처기 실기 시험에도 나왔음 ㅎㅎ;
코드
String s = "java.lang.Object";
String sb1 = s.substring(10); // 문자열의 10번재부터 문자열 끝까지 반환
String sb2 = s.substring(5,9); // 문자열의 5번부터 8번까지 반환(9는 반환 X)
결과
sb1 = Object
sb2 = lang
- String toLowerCase()
- 문자열을 모두 소문자로 변환
- String toUpperCase()
- 문자열을 모두 대문자로 변환
String s = "Hello";
String s1 = s.toLowerCase(); // 지정된 문자열을 소문자로 반환
String s2 = s.toUpperCase(); // 지정된 문자열을 대분자로 반환
// 결과
// s1 = hello
// s2 = HELLO
- String trim()
- 문자열의 양끝에 있는 공백을 없앤 결과를 반환
- 문자열 중간에 있는 공백은 제거 하지 않음
- 문자열은 변경 불가능하므로 새로운 문자열 객체로 생성 됨 -> 새로운 객체 주소 생성
String s = " Hello World ";
String s1 = s.trim(); // 지정된 문자열 맨앞,뒤의 공백을 제거(중간의 공백은 유지)
// 결과
// s1 = "Hello World" // 새로운 문자열 객체 생성
// s = " Hello World "; // s는 그대로 유지
- static String valueOf(boolean b)
- static String valueOf(char c)
- static String valueOf(int i)
- static String valueOf(long l)
- static String valueOf(float f)
- static String valueOf(double d)
- static String valueOf(Object o)
- 인자의 값을 String 타입으로 형변환 (빈 문자열과의 + 연산하는 것과 동일한 효과)
- valueOf가 성능이 더 좋지만 빈문자열이 코드 가독성이 좋아서 빈문자열과 + 연산으로 형변환 하는 경우도 종종있음
- 성능이 중요한 곳에서는 valueOf를 사용
- 인자의 값이 참조변수라면 toString()을 호출한 결과를 반환하여 객체의 참조값을 반환함
String b = String.valueOf(true);
String c = String.valueOf('a');
String i = String.valueOf(100);
String l = String.valueOf(100L);
String f = String.valueOf(10f);
String d = String.valueOf(10.0);
// 날짜와시간을 저장하는 클래스 -> 10장에서 상세히
java.util.Date dd = new java.util.Date();
String date = String.valueOf(dd)
// 결과
// b = "true"
// c = "a"
// i = "100"
// l = "100"
// f = "10.0"
// d = "10.0"
// date클래스의 객체 정보를 toString()메서드의 결과로 반환
// date = "Wed Jan 27 21:26:29 KST 2016"
** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의