๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Java

[Java DeepDive] - String (1) ๋ฌธ์ž์—ด ์ƒ์„ฑ

by ์ฃผ๋ฐœ2 2022. 10. 10.
๋ฐ˜์‘ํ˜•

๐Ÿ“Ž 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)๋กœ ์ƒ์„ฑํ•  ์‹œ ์ €์žฅ๋˜๋Š” ์˜์—ญ์ž…๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ์— ๋Œ€ํ•ด ํ• ๋‹น๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์‚ดํŽด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Memory

๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ƒ์„ฑํ•œ 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()

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์—์„œ ํ‰์†Œ์— ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋“ค์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ƒ

 

 

์ฐธ๊ณ  ๋ฌธ์„œ

 

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€