๐ String (1) - ๋ฌธ์์ด ์์ฑ
์๋ฐ์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํ์ ์ค ํ๋์ธ ๋ฌธ์์ด(String)์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
(์์ ์ฝ๋๋ ๊นํ๋ธ์์ ํ์ธํ์ค ์ ์์ผ๋ฉฐ, ๋ฒ์ ์ Java 11์ ์ฌ์ฉํ์ต๋๋ค.)
String ๋ฌธ์์ด ์์ฑ - new, literal
๋ณดํต ์๋ฐ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ new ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง๋ง, String์ ๊ฒฝ์ฐ ๋ฆฌํฐ๋ด(literal)์ ํตํด ๊ฐ์ ๋ฐ๋ก ํ ๋นํ ์ ์์ต๋๋ค.
public static void main(String[] args) {
final String str1 = "JuHyun"; // [1]
final String str2 = "JuHyun"; // [2]
final String str3 = new String("JuHyun"); // [3]
final String str4 = new String("JuHyun"); // [4]
}
ํ์ง๋ง ๋ณดํต String์ ์ฒซ ๋ฒ์งธ ๋ฐฉ์์ผ๋ก ์์ฑ์ ํ๋๋ฐ์, ์ค์ ๋ก๋ ์ ์ฝ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๋ ์์ญ์๋ ์ฐจ์ด๊ฐ ์กด์ฌํฉ๋๋ค.
[1] String Constant Pool ์ด๋ผ๋ ์์ญ์ ํ ๋น์ด ๋ฉ๋๋ค.
[2] String Constant Pool ์์ญ์ ์ด๋ฏธ "JuHyun"์ด๋ผ๋ ๊ฐ์ด ์กด์ฌํ๋ฏ๋ก, ํด๋น ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
[3] ์ผ๋ฐ ๊ฐ์ฒด์ฒ๋ผ Heap ์์ญ์ ํ ๋น์ด ๋ฉ๋๋ค.
[4] ์ผ๋ฐ ๊ฐ์ฒด์ฒ๋ผ Heap ์์ญ์ ํ ๋น์ด ๋ฉ๋๋ค. [3]์๋ ๋ณ๊ฐ๋ก ์๋ก์ด ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
String Constant Pool(SCP)
String Constant Pool(SCP)์ ๋ฌธ์์ด์ ๋ฆฌํฐ๋ด(literal)๋ก ์์ฑํ ์ ์ ์ฅ๋๋ ์์ญ์ ๋๋ค.
์ ์ฝ๋์ ๋ํด ํ ๋น๋๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฌธ์์ด ๋ฆฌํฐ๋ด๋ก ์์ฑํ str1, str2์ ๊ฒฝ์ฐ String Constant Pool ์์ญ ๋ด์ ๋์ผํ "JuHyun" ๋ฌธ์์ด์ ๊ฐ๋ฆฌํค๊ณ ์๋ ๋ฐ๋ฉด์, new ํค์๋๋ก ์์ฑํ str3, str4์ ๊ฒฝ์ฐ ๋์ผํ "JuHyun"์ด์ง๋ง, ๋ค๋ฅธ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํ๊ณ ์์ต๋๋ค.
์ ๊ทธ๋ฆผ์ ํตํด ์ ์ ์๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- String literal๋ก ์์ฑํ ๋ฌธ์์ด์ String Constant Pool ์์ญ์ ํ ๋น์ด ๋ฉ๋๋ค.
- String literal๋ก ์์ฑํ ๋ฌธ์์ด์ ๊ฐ("JuHyun")์ด String Constant Pool ์์ญ์ ์ด๋ฏธ ์กด์ฌํ๋ค๋ฉด, ์๋ก์ด ๋ฌธ์์ด์ ์์ฑํ๋ ๊ฒ ์๋ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.(Cache)
- new ํค์๋๋ก ์์ฑํ String์ ๊ฒฝ์ฐ, Heap ์์ญ์ ํ ๋น๋๊ธฐ ๋๋ฌธ์ String Constant Pool์ ๋์ผํ ๊ฐ์ด ์กด์ฌํ๋๋ผ๋ ๋ณ๋์ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
Java 7 ์ด์ ๋ฒ์ ์์๋ String Constant Pool ์์ญ์ PermGen ์์ญ์ ์กด์ฌํ์๋๋ฐ, ์ด ๊ณต๊ฐ์ ๋ฐํ์์ ํ์ฅํ ์ ์๊ณ , GC ๋์์์๋ ์ ์ธ๋๋ ์์ญ์ด์๊ธฐ์ Java 7๋ถํฐ๋ String Constant Pool ์์ญ์ด Heap ์์ญ์ผ๋ก ์ฎ๊ฒจ์ง๊ฒ ๋์์ต๋๋ค.
์ด๋ก ์ธํด JVM์ ์ํด GC ๋์์ด ๋๋ ์์ญ์ด๊ณ , ๊ฒฐ๋ก ์ ์ผ๋ก OOM์ด ๋ฐ์ํ ์ ์๋ ์ํ์์ ๋ํ ์ค์ด๋๋ ์ด์ ์ด ์์ต๋๋ค.
๋ฌธ์์ด ๋น๊ต: equals() ๋น๊ต์ == ๋น๊ต
๋ณดํต ๋ฌธ์์ด์ ๋น๊ตํ ๋ == ๋์ equals() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋๋ฐ์, ์ด์ ๊ด๋ จํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
@Test
void compareString() {
final String str1 = "JuHyun";
final String str2 = "JuHyun";
final String str3 = new String("JuHyun");
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(str1 == str2).isTrue();
softly.assertThat(str1 == str3).isFalse();
softly.assertThat(str2 == str3).isFalse();
softly.assertThat(str1.equals(str2)).isTrue();
softly.assertThat(str1.equals(str3)).isTrue();
softly.assertThat(str2.equals(str3)).isTrue();
});
}
String ํด๋์ค ๋ด์์ equals() ๋ฉ์๋ ์ฝ๋๋ ์์ ๊ฐ์๋ฐ์, ์ค์ ๋์ผํ ์ฃผ์๊ฐ์ ๊ฐ์ง๊ฑฐ๋ ํน์ ๊ฐ(๋ฌธ์์ด)์ด ๋์ผํ ๊ฒฝ์ฐ true๋ฅผ ๋ฆฌํดํฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ String์ ๋น๊ตํ ๋ ์ฃผ์๊ฐ์ ๋น๊ตํ๋ == ์ฐ์ฐ ๋์ ๊ฐ์ ๋น๊ตํ๋ equals๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ด์ ์ ๋๋ค.
(์ฌ๋ด์ด์ง๋ง Integer์ ๊ฒฝ์ฐ ์บ์ฑ ๋ ์ ์ ๋ฒ์ ๋ด์์๋ equals ๋์ ==์ฐ์ฐ์ ์ฌ์ฉํ์ฌ๋ ๋ฌธ์ ๊ฐ ์๋๋ฐ์, ๊ด๋ จํด์๋ ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.)
String ๋ถ๋ณ ํด๋์ค(final, Immutable)
String์ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ณ ํด๋์ค๋ก ์ค๊ณ๊ฐ ๋์ด์์ต๋๋ค.(Integer, Long, Double ๋ฑ์ ํด๋์ค๋ ๋ชจ๋ final์ ๋๋ค.)
์ String ํด๋์ค๊ฐ final(๋ถ๋ณ)์ธ๊ฐ์ ๋ํ ๋๋ต์ ์์ ๋ง์๋๋ ธ๋ ๋ฌธ์์ด ๋ฆฌํฐ๋ด๋ก ์์ฑ ์ ์ ์ฅ๋๋ ์์ญ์ธ String Constant Pool ์์ญ๊ณผ, ๋ณด์, ์ต์ ํ ๋ฑ์ ์ด์ ๊ฐ ์กด์ฌํ๋๋ฐ์ ์ด์ ๊ด๋ จํด์๋ ์๋ ํฌ์คํ ์ ์์ธํ ์ค๋ช ์ด ๋์ด์์ต๋๋ค.:
intern()
๋ฌธ์์ด์ ๋ฆฌํฐ๋ด ๋ฐฉ์์ผ๋ก ์์ฑํ ๋ String ๋ด๋ถ์ intern() ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
intern() ๋ฉ์๋๋ ๋ฌธ์์ด ์์ฑ ์ String Constant Pool ์์ญ์ ์ด๋ฏธ ์กด์ฌํ ๊ฒฝ์ฐ string์ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ Pool ์์ญ์ ์๋ก ์ถ๊ฐํ ํ String Object์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ๋ฆฌํดํฉ๋๋ค.
@Test
void testStringInternMethod() {
final String expected = "JuHyun";
final String str2 = new String("JuHyun");
final String actual = str2.intern();
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(actual.equals(expected)).isTrue();
softly.assertThat(actual == expected).isTrue();
});
}
์ ์ฝ๋์ ๋์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
[1] ๋ฆฌํฐ๋ด ๋ฐฉ์์ ํตํด ์ต์ด String Constant Pool ์์ญ์ "JuHyun"์ด๋ผ๋ ๋ฌธ์์ด์ ์ ์ฅํฉ๋๋ค.
[2] new ์ฐ์ฐ์๋ฅผ ํตํด Heap ์์ญ์ ํ ๋น๋๋ ์๋ก์ด ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
[3] intern() ๋ฉ์๋๋ฅผ ํตํด String Constant Pool ์์ญ์์ [1]์์ ์์ฑํ "JuHyun" ๋ฌธ์์ด์ ๊ฐ์ ธ์ต๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ expected ๋ฌธ์์ด๊ณผ actual ๋ฌธ์์ด์ ๋์ผํ String Constant Pool ์์ญ์ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ์กฐํ๊ณ , ์ฃผ์์ ๊ฐ ๋ชจ๋ ๋์ผํ ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
์ ๋ฆฌ
์ด์์ผ๋ก String ๋ฌธ์์ด์ ์์ฑํ๋ ๋ฐฉ๋ฒ๊ณผ ์ฃผ์์ ์ ๋ํด ์ ๋ฆฌํด ๋ณด์์ต๋๋ค.
ํ์์ == ๋น๊ต์ equals() ๋น๊ต๋ ์ด๋ค ๊ฒ์ด ๊ฐ ๋น๊ต์ธ์ง, ์ด๋ค ๊ฒ์ด ์ฃผ์ ๋น๊ต์ธ์ง ํญ์ ํท๊ฐ๋ ธ๋๋ฐ์, ์๋ฆฌ๋ฅผ ์๊ฐํ๋ฉฐ ์ ๊ทผํ๋ค ๋ณด๋ฉด ์ธ์ฐ์ง ์๋๋ผ๋ ์ดํดํ ์ ์์ ๋ฏํฉ๋๋ค.
๋ค์ ์๊ฐ์๋ String์์ ํ์์ ์์ฃผ ์ฌ์ฉํ๋ ํจ์๋ค์ ๋ํด ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค. ๐
์ฐธ๊ณ ๋ฌธ์
- https://www.baeldung.com/java-string-pool
- https://tecoble.techcourse.co.kr/post/2020-09-07-dive-into-java-string/
- https://medium.com/geekculture/a-deep-dive-into-java-string-e5f67ccbdba8
- https://www.mimul.com/blog/why-string-class-has-made-immutable-or-final-java/
'Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java DeepDive] - List (ArrayList) (2) | 2022.10.29 |
---|---|
[Java DeepDive] - String (2) ๋ด์ฅ ํจ์ (0) | 2022.10.23 |
[Java, ๋์์ธ ํจํด] - ์ฑ๊ธํด ํจํด(Singleton Pattern) (4) | 2021.10.24 |
[Java] - ๊น์ ๋ณต์ฌ(Deep Copy) vs ์์ ๋ณต์ฌ(Shallow Copy) (1) | 2021.07.30 |
[Java] - Project Lombok(๋กฌ๋ณต) (0) | 2021.06.20 |
๋๊ธ