일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- multiparfile데이터
- HTTP프로토콜
- HttpServlet
- 옵티마이저
- 공유기작동방식
- 왜불변객체인가
- rest api
- Wrapper class
- 동등성동일성
- 옵티마저
- 불변객체
- 데이터베이스파서
- 래퍼클래스
- 프로세스 생성
- 디스패처서블릿
- multipart바인딩
- fcm데이터구조
- 스프링요청반응
- 클라이언트요청반응
- equals
- DispatcherServlet
- httpservlet기술
- 동기비동기블로킹논블로킹
- fcm성능비교
- rest api 검증
- 중첩클래스
- java enum
- biblecash
- 검증 실패 예외처리
- fcmv1
- Today
- Total
개발은 아름다워
[ Java ] String은 기본타입과는 달라요~ 본문
자바에서 문자를 다루는 대표적인 타입은 char , String 2가지가 있다.
기본형인 char는 문자 하나를 다룰 때 사용한다.
char를 사용해서 여러 문자를 나열하려면 char[ ]을 사용해야 한다.
하지만 char[ ] 을 직접 다루는 방법은 매우 불편하기 때문에 자바는 문자열을 매우 편리하게 다룰 수 있는 String 클래스를 제공한다.
String을 통해 문자열을 생성하는 2가지 방법
String srt1 = "hello";
String str2 = new String("hello");
String은 클래스이다.
기본형이 아니라 참조형이라는 것이다.
str1의 변수에는 인스턴스의 참조값만 들어갈 수 있는데, 문자열은 매우 자주 사용됨으로 편의상 쌍따옴표로 문자열을 감싸면 자바 언어에서 "hello"를 new String("hello")로 변경해준다.
String 클래스 구조
String도 클래스이기 때문에 필드와 메서드를 갖는다.
- 필드 : private final byte[ ] value;
- 메서드 : length, charAt,trim 등
String 클래스와 참조형
String 클래스는 기본형이 아니라 참조형이다.
참조형은 변수에 계산할 수 있는 값이 들어있는 것이 아니라 x001과 같이 계산할 수 없는 참조값이 들어있다.
따라서 원칙적으로 + 같은 연산을 할 수 없다.
하지만 문자열은 너무 자주 다루어지기 때문에 자바 언어에서는 편의상 특별히 + 연산을 제공한다.
String a = "hello";
String b = " java";
System.out.println(a+b); // hello java
String 클래스 - 비교
String 클래스를 비교할 때는 == 비교가 아니라 항상 equals() 비교를 해야한다. 동등성비교!
String str1 = new String("hello"); // x001
String str2 = new String("hello") // x002
str1 == str2 // false 왜냐하면 참조 값이 다르기 때문 (동일성 비교)
str1.equals(str2); // true (동등성 비교)
String str3 = "hello"; // x003
String str4 = "hello"; // x003
str3 == str4 // true 문자열 풀에 같은 인스턴스 참조값을 가리키므로 참이다.
str3.equals(str4) // true
String str3 = "hello"; 와 같이 문자열 리터럴을 사용하는 경우
자바는 메모리 효율성과 성능 최적화를 위해 문자열 풀을 사용한다.
자바가 실행되는 시점에 클래스에 문자열 리터럴이 있으면 문자열 풀에 String 인스턴스를 미리 만들어둔다.
이 때 같은 문자열이 있으면 새로운 인스턴스를 만들지 않는다.
String str3 = "hello"와 같이 문자열 리터럴을 사용하면 문자열 풀에서 "hello"라는 문자를 가진 String 인스턴스를 찾는다. 그리고 인스턴스의 참조값을 반환한다.
String str4 = "hello";의 경우 "hello" 문자열 리터럴을 사용하므로 문자열 풀에서 str3와 같은 x003 참조값을 사용한다.
문자열 풀 덕분에 같은 문자를 사용하는 경우 메모리 사용을 줄이고 문자를 만드는 시간도 줄어들기 때문에 성능도 최적화 할 수 있다.
문자열 풀이 있는 이유
풀은 자원이 모여있는 곳을 의미한다.
프로그래밍에서 풀은 공용 자원을 모아둔 곳을 뜻한다.
여러 곳에서 함께 사용할 수 있는 객체를 필요할 때 마다 생성하고, 제거하는 것은 비효율적이다.
대신 문자열 풀에 필요한 String 인스턴스를 미리 만들어두고 여러곳에서 재사용할 수 있다면 성능과 메모리를 더 최적화 할 수 있는 것이다.
참고로 문자열 풀은 힙 영역을 사용하며 문자열 풀에서 문자를 찾을 떄는 해시 알고리즘을 사용하기 때문에 매우 빠른 속도로 원하는 String 인스턴스를 찾을 수 있다.
그럼 왜 문자열 비교시 ==동일성 비교가 아니라 equals동등성 비교를 하는게 좋은것일까??
왜냐하면 리터럴로 만든 경우가 있을 수 있고 new String() 생성자로 만드는 경우가 있을 수 있기 때문이다.
동일성 비교로 두 String 인스턴스를 비교하는 메서드가 있다하면
private static boolean isSame(String a, Stirng b){
return a==b;
}
isSame(str1,str2) // false
isSame(str3,str3) // true
이렇게 될 수 있으므로 따라서 Sring 인스턴스 비교시에는 항상 equals를 사용해야한다.
String 객체는 불변 객체
String 클래스를 보면 필드가 private final byte[ ] value;로 되어 있음을 알 수 있다.
즉, String 인스턴스가 생성되면 불변 객체로 생성됨을 알 수 있다.
그렇다면 왜 String 인스턴스를 불변 객체로 만든걸까?
만약 String 인스턴스가 불변객체가 아니라면 문자열 풀에 있는 인스턴스 값이 중간에 바뀔 경우 같은 문자열을 참고하는 다른 변수의 값도 함께 변경될 수 있기 때문이다.
즉, 의도치 않은 사이드 이펙트가 발생할 수 있기 때문이다.
따라서 String 인스턴스를 불변 객체로 만들어 추후 사이드 이펙트가 발생하지 않도록 만든 것이다.
StringBuilder 가변 String
String 객체가 불변인 것이기 사이드 이펙트를 막을 수 있는 장점이 있지만, 문자들을 더 해야만 하는 경우 단점이 될 수도 있다.
왜냐하면 불변인 String 객체는 내부 값을 변경할 수 없기 때문이다.
따라서 변경된 값을 기반으로 새로운 String 객체를 생성한다.
객체를 생성할 때마다 자원을 낭비하게 되는 것이다.
이 문제를 해결하기 위해 불변이 아닌 가변 String 객체를 생성할 수 있는 StringBuilder 클래스를 쓰면 된다.
물론 가변의 경우 사이드 이펙트에 주의해서 사용해야 한다.
그래서 StringBuilder는 보통 문자열을 변경하는 동안만 사용하다가 문자열 변경이 끝나면 안전한(불변) String으로 변환하는 것이 좋다.
'자바' 카테고리의 다른 글
[ Java ] 동기화 비동기화 블로킹 논블로킹 외우지말고 이해하자 (0) | 2024.10.30 |
---|---|
[ Java ] 불변객체는 왜 필요한걸까? ver2 (0) | 2024.10.24 |
[ Java ] 추상클래스는 왜 필요한걸까? (추상클래스 그리고 인터페이스) (1) | 2024.10.24 |
[ Java ] 불변객체는 왜 필요할까? (1) | 2024.10.24 |
[ Java ] Java는 왜 callbyValue만 되는걸까? (1) | 2024.10.24 |