CodeGym /Java Blog /๋ฌด์ž‘์œ„์˜ /Java์˜ ์ตœ์ข… ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ด…์‹œ๋‹ค.
John Squirrels
๋ ˆ๋ฒจ 41
San Francisco

Java์˜ ์ตœ์ข… ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ด…์‹œ๋‹ค.

๋ฌด์ž‘์œ„์˜ ๊ทธ๋ฃน์— ๊ฒŒ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
์ž๋ฐ”์—๋Š” final์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค, ๋ฉ”์†Œ๋“œ, ๋ณ€์ˆ˜(๋ฉ”์†Œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜ ํฌํ•จ)์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ final ํ‚ค์›Œ๋“œ๋Š” ํด๋ž˜์Šค๊ฐ€ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ƒ์†์ด ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค... ์ด๋Š” ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ(๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ) ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, String ํด๋ž˜์Šค๋Š” final๋กœ ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค.

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
๋˜ํ•œ ์ตœ์ข… ์ˆ˜์ •์ž๋Š” ์ถ”์ƒ ํด๋ž˜์Šค(ํ‚ค์›Œ๋“œ abstract๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค)์—๋Š” ์ƒํ˜ธ ๋ฐฐํƒ€์ ์ธ ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์— ์œ ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ ํ•œ์ •์ž๋Š” ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›๋ž˜ ๊ตฌํ˜„์˜ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

    public class SuperClass {
        public final void printReport() {
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
๊ธฐ๋ณธ ์œ ํ˜•์˜ ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ final ํ‚ค์›Œ๋“œ๋Š” ํ•œ ๋ฒˆ ํ• ๋‹น๋œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฐธ์กฐ ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ ๊ฐœ์ฒด๊ฐ€ ํ• ๋‹น๋œ ํ›„์—๋Š” ํ•ด๋‹น ๊ฐœ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฑด ์ค‘์š”ํ•˜๋‹ค! ์ฐธ์กฐ๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์ง€๋งŒ ๊ฐœ์ฒด์˜ ์ƒํƒœ๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Java 8์€ ์‚ฌ์‹ค์ƒ ์ตœ์ข…์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ฐœ๋…์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณ€์ˆ˜(๋ฉ”์†Œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜ ํฌํ•จ)์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์€ final ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ณ€์ˆ˜์˜ ๊ฐ’์€ ์ดˆ๊ธฐํ™” ํ›„์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ์—†์ด ์ด๋Ÿฌํ•œ ๋ณ€์ˆ˜์— final ํ‚ค์›Œ๋“œ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํšจ๊ณผ์ ์œผ๋กœ ์ตœ์ข… ๋ณ€์ˆ˜๋Š” ๋กœ์ปฌ ํด๋ž˜์Šค(๋กœ์ปฌ ๋‚ด๋ถ€ ํด๋ž˜์Šค), ์ต๋ช… ํด๋ž˜์Šค(์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค) ๋ฐ ์ŠคํŠธ๋ฆผ(Stream API) ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
        }
์ž, ์ž ์‹œ ์ธํ„ฐ๋ทฐ๋ฅผ ํ•ด๋ณด์ž. ๊ฒฐ๊ตญ CodeGym ๊ณผ์ •์„ ์ด์ˆ˜ํ•˜๋Š” ๋ชฉํ‘œ๋Š” Java ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด ํฅ๋ฏธ๋กญ๊ณ  ๋ณด์ˆ˜๊ฐ€ ์ข‹์€ ์ง์—…์„ ์ฐพ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž, ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
  1. ์ตœ์ข… ์„ ์–ธ๋œ ๋ฐฐ์—ด์— ๋Œ€ํ•ด ๋ฌด์—‡์„ ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

  2. ์šฐ๋ฆฌ๋Š” String ํด๋ž˜์Šค๊ฐ€ ๋ถˆ๋ณ€์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค๋Š” final๋กœ ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด ๊ฐ’์€ final ํ‚ค์›Œ๋“œ๋กœ ํ‘œ์‹œ๋œ char ๋ฐฐ์—ด์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  String ๊ฐ์ฒด์˜ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์‹ค์ œ ๋ฉด์ ‘ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฐ์Šต์— ๋”ฐ๋ฅด๋ฉด ๋งŽ์€ ํ›„๋ณด์ž๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋Œ€๋‹ตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ฐธ์กฐ ๋ณ€์ˆ˜์— ๋Œ€ํ•ด final ํ‚ค์›Œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ์‹์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์ฝ”๋“œ์งํŒ€์— ์ž‘์€ ๋ถ€ํƒ ํ•˜๋‚˜ ํ• ๊ฒŒ์š”. ํ…์ŠคํŠธ ํŽธ์ง‘๊ธฐ๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋‚ด์šฉ์„ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์‹ญ์‹œ์˜ค. ๋‹ต๋ณ€:
  1. ๋ฐฐ์—ด์€ ๊ฐ์ฒด์ด๋ฏ€๋กœ final ํ‚ค์›Œ๋“œ๋Š” ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ํ• ๋‹น๋˜๋ฉด ์ฐธ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ฐœ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    
            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
    
  2. ๊ทธ๋ž˜ ์šฐ๋ฆฌ๋Š” ํ•  ์ˆ˜์žˆ์–ด. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ๊นŒ๋‹ค๋กœ์šด ์ตœ์ข… ํ‚ค์›Œ๋“œ๊ฐ€ ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Reflection API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        field.setAccessible(true);
        // Set a new value
        field.set(value, "CodeGym".toCharArray());

        System.out.println(value);

        /* Output:
         * Old value
         * CodeGym
         */
    }
}
์ด๋Ÿฐ ์‹์œผ๋กœ ๊ธฐ๋ณธ ์œ ํ˜•์˜ ์ตœ์ข… ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ๋‹ค๋ฉด ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ตœ์ข… int ํ•„๋“œ๊ฐ€ ์žˆ๋Š” Java ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  Reflection API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด ๋ณด์‹ญ์‹œ์˜ค. ๋ชจ๋‘์—๊ฒŒ ํ–‰์šด์„ ๋น•๋‹ˆ๋‹ค!
์ฝ”๋ฉ˜ํŠธ
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION