λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ“— Book/μžλ°”μ˜ 정석

6-3μž₯ λ³€μˆ˜μ™€ λ©”μ„œλ“œ δΈ‹ (3.7 ~ 3.12)

by hyeon-z 2023. 4. 18.

 

7. JVM의 λ©”λͺ¨λ¦¬ ꡬ쑰

* cvλŠ” 클래슀 λ³€μˆ˜, lvλŠ” μ§€μ—­ λ³€μˆ˜, ivλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό λœ»ν•œλ‹€.

 

λ©”μ„œλ“œ μ˜μ—­ (method area)

 

ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑 μ–΄λ–€ ν΄λž˜μŠ€κ°€ μ‚¬μš©λ˜λ©΄, JVM은 ν•΄λ‹Ή 클래슀의 클래슀 파일(*.class)을 μ½μ–΄μ„œ λΆ„μ„ν•˜μ—¬ ν΄λž˜μŠ€μ— λŒ€ν•œ 정보λ₯Ό(클래슀 데이터)λ₯Ό 이곳에 μ €μž₯ν•œλ‹€. 이 λ–„, κ·Έ 클래슀의 ν΄λž˜μŠ€ λ³€μˆ˜(class variable)도 이 μ˜μ—­μ— ν•¨κ»˜ μƒμ„±λœλ‹€.

 

νž™ (heap)

 

μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜λŠ” 곡간. ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑 μΈμŠ€ν„΄μŠ€λŠ” λͺ¨λ‘ 이곳에 μƒμ„±λœλ‹€. 즉, μΈμŠ€ν„΄μŠ€ λ³€μˆ˜(instance variable)듀이 μƒμ„±λ˜λŠ” 곡간이닀.

 

ν˜ΈμΆœμŠ€νƒ (call stack λ˜λŠ” execution stack)

 

λ©”μ„œλ“œμ˜ μž‘μ—…μ— ν•„μš”ν•œ λ©”λͺ¨λ¦¬ 곡간을 μ œκ³΅ν•œλ‹€. λ©”μ„œλ“œκ°€ 호좜되면, ν˜ΈμΆœμŠ€νƒμ— 호좜된 λ©”μ„œλ“œλ₯Ό μœ„ν•œ λ©”λͺ¨λ¦¬κ°€ ν• λ‹Ήλ˜λ©°, 이 λ©”λͺ¨λ¦¬λŠ” λ©”μ„œλ“œκ°€ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” λ™μ•ˆ μ§€μ—­λ³€μˆ˜(λ§€κ°œλ³€μˆ˜ 포함)λ“€κ³Ό μ—°μ‚°μ˜ 쀑간 κ²°κ³Ό λ“±μ„ μ €μž₯ν•˜λŠ”λ° μ‚¬μš©λœλ‹€. 그리고 λ©”μ„œλ“œκ°€ μž‘μ—…μ„ 마치면 ν• λ‹Ήλ˜μ—ˆλ˜ λ©”λͺ¨λ¦¬ 곡간은 λ°˜ν™˜λ˜μ–΄ λΉ„μ›Œμ§„λ‹€.

 

ν˜ΈμΆœμŠ€νƒμ˜ λ³€ν™”

class CallStackTest {
    public static void main(String[] args) {
    	firstMethod() ; // staticλ©”μ„œλ“œλŠ” 객체 생성없이 ν˜ΈμΆœκ°€λŠ₯ν•˜λ‹€.
    }
    static void firstMethod() {
    	secondMethod();
    }
    static void secondMethod() {
    	System.out.println("secondMethod()");
    }
}

 

 

1~2: JVM에 μ˜ν•΄μ„œ mainλ©”μ„œλ“œκ°€ 호좜됨으둜써 ν”„λ‘œκ·Έλž¨μ΄ μ‹œμž‘λœλ‹€. μ΄λ•Œ, ν˜ΈμΆœμŠ€νƒμ—λŠ” mainλ©”μ„œλ“œλ₯Ό μœ„ν•œ λ©”λͺ¨λ¦¬ 곡간이 ν• λ‹Ήλ˜κ³  mainλ©”μ„œλ“œμ˜ μ½”λ“œκ°€ μˆ˜ν–‰λœλ‹€.

 

3: mainλ©”μ„œλ“œμ—μ„œ firstMethod()λ₯Ό ν˜ΈμΆœν•œ μƒνƒœμ΄λ‹€. 아직 mainλ©”μ„œλ“œκ°€ λλ‚œ 것이 μ•„λ‹ˆλ―€λ‘œ mainλ©”μ„œλ“œλŠ” 호좜 μŠ€νƒμ— λŒ€κΈ°μƒνƒœλ‘œ λ‚¨μ•„μžˆκ³  firstMethod()의 μˆ˜ν–‰μ΄ μ‹œμž‘λœλ‹€. 

 

4. firstMethod()μ—μ„œ λ‹€μ‹œ secondMethod()λ₯Ό ν˜ΈμΆœν–ˆλ‹€. firstMethod()λŠ” secondMethod()κ°€ μˆ˜ν–‰μ„ 마칠 λ•ŒκΉŒμ§€ λŒ€κΈ°μƒνƒœμ— 있게 λœλ‹€. secondMethod()κ°€ μˆ˜ν–‰μ„ λ§ˆμ³μ•Ό firstMethod()의 λ‚˜λ¨Έμ§€ λ¬Έμž₯듀이 μˆ˜ν–‰λ  수 있기 λ•Œλ¬Έμ΄λ‹€.

 

5. secondMethod()μ—μ„œ println()을 ν˜ΈμΆœν–ˆλ‹€. printlnλ©”μ„œλ“œμ— μ˜ν•΄ 'secondMethod()'κ°€ 화면에 좜λ ₯λœλ‹€.

 

6. printlnλ©”μ„œλ“œμ˜ μˆ˜ν–‰μ΄ μ™„λ£Œλ˜μ–΄ ν˜ΈμΆœμŠ€νƒμ—μ„œ 사라지고 μžμ‹ μ„ ν˜ΈμΆœν•œ secondMethod()둜 λ˜λŒμ•„κ°„λ‹€. λŒ€κΈ° μ€‘μ΄λ˜ secondMethod()λŠ” println()을 ν˜ΈμΆœν•œ 이후뢀터 μˆ˜ν–‰μ„ μž¬κ°œν•œλ‹€.

 

7. secondMethod()에 더 이상 μˆ˜ν–‰ν•  μ½”λ“œκ°€ μ—†μœΌλ―€λ‘œ μ’…λ£Œλ˜κ³ , μžμ‹ μ„ ν˜ΈμΆœν•œ firstMethod()둜 λŒμ•„κ°„λ‹€.

 

8. firstMethod()에도 더 이상 μˆ˜ν–‰ν•  μ½”λ“œκ°€ μ—†μœΌλ―€λ‘œ μ’…λ£Œλ˜κ³ , μžμ‹ μ„ ν˜ΈμΆœν•œ mainλ©”μ„œλ“œλ‘œ λŒμ•„κ°„λ‹€.

 

9. mainλ©”μ„œλ“œμ—λ„ 더 이상 μˆ˜ν–‰ν•  μ½”λ“œκ°€ μ—†μœΌλ―€λ‘œ μ’…λ£Œλ˜μ–΄, ν˜ΈμΆœμŠ€νƒμ€ μ™„μ „νžˆ λΉ„μ›Œμ§€κ²Œ 되고 ν”„λ‘œκ·Έλž¨μ€ μ’…λ£Œλœλ‹€.

 

 

ν˜ΈμΆœμŠ€νƒμ˜ νŠΉμ§•

- λ©”μ„œλ“œκ°€ 호좜되면 μˆ˜ν–‰μ— ν•„μš”ν•œ 만큼의 λ©”λͺ¨λ¦¬λ₯Ό μŠ€νƒμ— ν• λ‹Ήλ°›λŠ”λ‹€.

- λ©”μ„œλ“œκ°€ μˆ˜ν–‰μ„ 마치고 λ‚˜λ©΄ μ‚¬μš©ν–ˆλ˜ λ©”λͺ¨λ¦¬λ₯Ό λ°˜ν™˜ν•˜κ³  μŠ€νƒμ—μ„œ μ œκ±°λœλ‹€.

- ν˜ΈμΆœμŠ€νƒμ˜ 제일 μœ„μ— μžˆλŠ” λ©”μ„œλ“œκ°€ ν˜„μž¬ μ‹€ν–‰ 쀑인 λ©”μ„œλ“œμ΄λ‹€.

- μ•„λž˜μ— μžˆλŠ” λ©”μ„œλ“œκ°€ λ°”λ‘œ μœ„μ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ λ©”μ„œλ“œμ΄λ‹€.

 

 

8. κΈ°λ³Έν˜• λ§€κ°œλ³€μˆ˜μ™€ μ°Έμ‘°ν˜• λ§€κ°œλ³€μˆ˜

 

κΈ°λ³Έν˜• λ§€κ°œλ³€μˆ˜: λ³€μˆ˜μ˜ 값을 읽기만 ν•  수 μžˆλ‹€. (read only)

μ°Έμ‘°ν˜• λ§€κ°œλ³€μˆ˜: λ³€μˆ˜μ˜ 값을 읽고 λ³€κ²½ν•  수 μžˆλ‹€. (read & write)

 

κΈ°λ³Έν˜• λ§€κ°œλ³€μˆ˜ μ˜ˆμ‹œ

 

class Data {
    int x;
}

class Test {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x);

        change(d.x);

        System.out.println("After change(x)");
        System.out.println("main() : x = " + d.x);
    }

    static void change(int x) {  // κΈ°λ³Έν˜• λ§€κ°œλ³€μˆ˜
        x = 1000;
        System.out.println("change() : x = " + x);
    }
}

 

μ‹€ν–‰ κ²°κ³Ό

main() : x = 10
change() : x = 1000
After change(x)
main() : x = 10

 

changeλ©”μ„œλ“œμ—μ„œ mainλ©”μ„œλ“œλ‘œλΆ€ν„° λ„˜κ²¨λ°›μ€ d.x의 값을 1000으둜 λ³€κ²½ν–ˆλŠ”λ°λ„ mainλ©”μ„œλ“œμ—μ„œλŠ” d.x의 값이 κ·ΈλŒ€λ‘œμ΄λ‹€.  κ·Έ μ΄μœ λŠ” d.x의 값이 λ³€κ²½λœ 것이 μ•„λ‹ˆλΌ, changeλ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜ x의  값이 λ³€κ²½λœ 것이기 λ•Œλ¬Έμ΄λ‹€. 

즉, 원본이 μ•„λ‹Œ 볡사본이 λ³€κ²½λœ 것이라 μ›λ³Έμ—λŠ” μ•„λ¬΄λŸ° 영ν–₯을 λ―ΈμΉ˜μ§€ λͺ»ν•œλ‹€.

이처럼 κΈ°λ³Έν˜• λ§€κ°œλ³€μˆ˜λŠ” λ³€μˆ˜μ— μ €μž₯된 κ°’λ§Œ 읽을 수 μžˆμ„ 뿐 λ³€κ²½ν•  μˆ˜λŠ” μ—†λ‹€.

 

 

μ°Έμ‘°ν˜• λ§€κ°œλ³€μˆ˜ μ˜ˆμ‹œ 1

 

class Test {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x);

        change(d);

        System.out.println("After change(d)");
        System.out.println("main() : x = " + d.x);
    }

    static void change(Data d) {
        d.x = 1000;
        System.out.println("change() : x = " + d.x);
    }
}

 

μ‹€ν–‰ κ²°κ³Ό

main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000

 

changeλ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜λ₯Ό μ°Έμ‘°ν˜•μœΌλ‘œ μ„ μ–Έν–ˆκΈ° λ•Œλ¬Έμ—, x의 값이 μ•„λ‹Œ μ£Όμ†Œκ°€ λ§€κ°œλ³€μˆ˜ d에 λ³΅μ‚¬λ˜μ—ˆλ‹€. 이제 mainλ©”μ„œλ“œμ˜ μ°Έμ‘°λ³€μˆ˜ d와 changeλ©”μ„œλ“œμ˜ μ°Έμ‘°λ³€μˆ˜ dλŠ” 같은 객체λ₯Ό κ°€λ¦¬ν‚€κ²Œ λœλ‹€. λ”°λΌμ„œ λ§€κ°œλ³€μˆ˜ d둜 x의 값을 μ½λŠ” 것과 λ³€κ²½ν•˜λŠ” 것이 λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€. 

 

μ°Έμ‘°ν˜• λ§€κ°œλ³€μˆ˜ μ˜ˆμ‹œ 2

 

class Test {
    public static void main(String[] args) {
        int[] x = {10};
        System.out.println("main() : x = " + x[0]);

        change(x);

        System.out.println("After change(x)");
        System.out.println("main() : x = " + x[0]);

    }

    static void change(int[] x) {
        x[0] = 1000;
        System.out.println("change() : x = " + x[0]);
    }
}

 

배열도 객체와 같이 μ°Έμ‘°λ³€μˆ˜λ₯Ό 톡해 데이터가 μ €μž₯된 곡간에 μ ‘κ·Όν•œλ‹€. 이전 μ˜ˆμ œμ™€ 같이 λ³€μˆ˜ x도 intλ°°μ—΄ νƒ€μž…μ˜ μ°Έμ‘°λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ— 같은 κ²°κ³Όλ₯Ό μ–»λŠ”λ‹€.

 

9. μ°Έμ‘°ν˜• λ°˜ν™˜νƒ€μž…

class Data {
    int x;
}

class Test {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;

        Data d2 = copy(d);
        
        System.out.println("d.x = " + d.x);
        System.out.println("d2.x = " + d2.x);

    }

    static Data copy(Data d) {
        Data tmp = new Data();
        tmp.x = d.x;

        return tmp;
    }
}

 

μ‹€ν–‰ κ²°κ³Ό

d.x = 10
d2.x = 10

 

μ‹€ν–‰ κ³Όμ •

1. copyλ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ μ°Έμ‘°λ³€μˆ˜ d의 값이 λ§€κ°œλ³€μˆ˜ d에 λ³΅μ‚¬λœλ‹€.

2. μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•œ λ‹€μŒ, d.x에 μ €μž₯된 값을 tmp.x에 λ³΅μ‚¬ν•œλ‹€.

3. copyλ©”μ„œλ“œκ°€ μ’…λ£Œλ˜λ©΄μ„œ λ°˜ν™˜ν•œ tmp의 값은 μ°Έμ‘°λ³€μˆ˜ d2에 μ €μž₯λœλ‹€.

4. copyλ©”μ„œλ“œκ°€ μ’…λ£Œλ˜μ–΄ tmpλŠ” μ‚¬λΌμ‘Œμ§€λ§Œ, d2둜 μƒˆλ‘œμš΄ 객체λ₯Ό λ‹€λ£° 수 μžˆλ‹€.

 

βœ… λ°˜ν™˜νƒ€μž…μ΄ 'μ°Έμ‘°ν˜•'μ΄λΌλŠ” 것은 λ©”μ„œλ“œκ°€ '객체의 μ£Όμ†Œ'λ₯Ό λ°˜ν™˜ν•œλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.

 

10. μž¬κ·€ν˜ΈμΆœ (recursive call)

πŸ’‘λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œ λ©”μ„œλ“œ μžμ‹ μ„ λ‹€μ‹œ ν˜ΈμΆœν•˜λŠ” 것

 

μž¬κ·€ 호좜 μ˜ˆμ‹œ

 

νŒ©ν† λ¦¬μ–Ό 식: f(n) = n * f(n-1), 단 f(1) = 1

class Test {
    public static void main(String[] args) {
        System.out.println(factorial(2));
    }

    static int factorial(int n) {
        int result;

        if (n == 1) {
            result = 1;
        } else {
            result = n * factorial(n - 1);
        }

        return result;
    }
}

 

μ‹€ν–‰ κ³Όμ •

1. factorial(2)λ₯Ό ν˜ΈμΆœν•˜λ©΄μ„œ λ§€κ°œλ³€μˆ˜ n에 2κ°€ λ³΅μ‚¬λœλ‹€.

2. 'return 2 * factorial(1);'을 κ³„μ‚°ν•˜λ €λ©΄ factorial(1)을 ν˜ΈμΆœν•œ κ²°κ³Όκ°€ ν•„μš”ν•˜λ‹€. factorial(1)이 호좜되고 λ§€κ°œλ³€μˆ˜ n에 1이 λ³΅μ‚¬λœλ‹€.

3. if문의 쑰건식이 μ°Έμ΄λ―€λ‘œ 1을 λ°˜ν™˜ν•˜λ©΄μ„œ λ©”μ„œλ“œλŠ” μ’…λ£Œλœλ‹€. 그리고 factorial(1)을 ν˜ΈμΆœν•œ 곳으둜 λ˜λŒμ•„κ°„λ‹€.

4. 이제 factorial(1)의 결괏값인 1을 μ–»μ—ˆμœΌλ―€λ‘œ, return문이 λ‹€μŒμ˜ κ³Όμ •μœΌλ‘œ κ³„μ‚°λœλ‹€.

return 2 * factorial(1);
-> return 2 * 1;
-> return 2;

 

μž¬κ·€ν˜ΈμΆœμ˜ 주의점

 

- μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš° μ—λŸ¬

μœ„μ˜ μ˜ˆμ‹œμ˜ 경우 λ§€κ°œλ³€μˆ˜ n의 값이 0μ΄κ±°λ‚˜ 100,000와 같이 큰 값이면 계속 μž¬κ·€ν˜ΈμΆœμ΄ μΌμ–΄λ‚˜ μŠ€νƒμ— 데이터가 μŒ“μΈλ‹€. μ–΄λŠ μ‹œμ μ— 이λ₯΄λŸ¬μ„œλŠ” κ²°κ΅­ μŠ€νƒμ˜ μ €μž₯ν•œκ³„λ₯Ό λ„˜κ²Œλ˜κ³ , 'μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš° μ—λŸ¬'κ°€ λ°œμƒν•œλ‹€.

 

κ°œμ„ λœ μ½”λ“œ

class Test {
    public static void main(String[] args) {
        System.out.println(factorial(2));
    }

    static int factorial(int n) {
        if (n <= 0 || n > 12) {
            return -1;
        }
        if (n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }
}

n의 μƒν•œκ°’μ„ 12둜 μ •ν•œ μ΄μœ λŠ” 13!의 값이 λ©”μ„œλ“œ factorial의 λ°˜ν™˜νƒ€μž…μΈ int의 μ΅œλŒ“κ°’(μ•½ 20μ–΅)보닀 크기 λ•Œλ¬Έμ΄λ‹€.

 

반볡문으둜 κ΅¬ν˜„

 

class Test {
    public static void main(String[] args) {
        System.out.println(factorial(2));
    }

    static int factorial(int n) {
        int result = 1;

        while (n != 0) {
            result *= n--;
        }
        return result;
    }
}

μž¬κ·€ν˜ΈμΆœκ³Ό 달리 λ§Žμ€ 수의 λ°˜λ³΅μ—λ„ 'μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš° μ—λŸ¬'와 같은 λ©”λͺ¨λ¦¬ λΆ€μ‘± 문제λ₯Ό κ²ͺμ§€ μ•Šμ„ 뿐만 μ•„λ‹ˆλΌ 속도도 λΉ λ₯΄λ‹€.

 

11. 클래슀 λ©”μ„œλ“œ(static λ©”μ„œλ“œ)와 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ

 

μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ™€ κ΄€λ ¨λœ μž‘μ—…μ„ ν•˜λŠ”, 즉 λ©”μ„œλ“œμ˜ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ”λ° μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό ν•„μš”λ‘œ ν•˜λŠ” λ©”μ„œλ“œμ΄λ‹€. μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€(객체)λ₯Ό μƒμ„±ν•΄μ•Όλ§Œ λ§Œλ“€μ–΄μ§€λ―€λ‘œ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ μ—­μ‹œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•΄μ•Όλ§Œ ν˜ΈμΆœν•  수 μžˆλ‹€.

 

클래슀 λ§€μ„œλ“œλŠ” μΈμŠ€ν„΄μŠ€μ™€ κ΄€κ³„μ—†λŠ”(μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ‚˜ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”) λ©”μ„œλ“œμ΄λ‹€.

 

* 멀버 λ³€μˆ˜: 클래슀 μ˜μ—­μ— μ„ μ–Έλœ λ³€μˆ˜, static이 뢙은 것은 클래슀 λ³€μˆ˜(static λ³€μˆ˜), static이 λΆ™μ§€ μ•Šμ€ 것은 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ΄λ‹€. 

 

1. 클래슀λ₯Ό 섀계할 λ•Œ, 멀버 λ³€μˆ˜ 쀑 λͺ¨λ“  μΈμŠ€ν„΄μŠ€μ— κ³΅ν†΅μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 것에 static을 뢙인닀.

 

μƒμ„±λœ 각 μΈμŠ€ν„΄μŠ€λŠ” 독립적이기 λ•Œλ¬Έμ— 각 μΈμŠ€ν„΄μŠ€μ˜ λ³€μˆ˜λŠ” μ„œλ‘œ λ‹€λ₯Έ 값을 μœ μ§€ν•œλ‹€. κ·ΈλŸ¬λ‚˜ λͺ¨λ“  μΈμŠ€ν„΄μŠ€μ—μ„œ 같은 값이 μœ μ§€λ˜μ–΄μ•Ό ν•˜λŠ” λ³€μˆ˜λŠ” static을 λΆ™μ—¬μ„œ 클래슀 λ³€μˆ˜λ‘œ μ •μ˜ν•΄μ•„ν•œλ‹€.

 

2. 클래슀 λ³€μˆ˜(static λ³€μˆ˜)λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ μ‚¬μš©ν•  수 μžˆλ‹€.

 

static이 뢙은 λ³€μˆ˜(클래슀 λ³€μˆ˜)λŠ” ν΄λž˜μŠ€κ°€ λ©”λͺ¨λ¦¬μ— 올라갈 λ•Œ 이미 μžλ™μ μœΌλ‘œ μƒμ„±λœλ‹€.

 

3. 클래슀 λ©”μ„œλ“œ(static λ©”μ„œλ“œ)λŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

 

μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€κ°€ λ°˜λ“œμ‹œ μ‘΄μž¬ν•΄μ•Όλ§Œ μ‚¬μš©ν•  수 μžˆλŠ”λ°, 클래슀 λ©”μ„œλ“œ(static이 뢙은 λ©”μ„œλ“œ)λŠ” μΈμŠ€ν„΄μŠ€ 생성 없이 ν˜ΈμΆœκ°€λŠ₯ν•˜λ―€λ‘œ 클래슀 λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜μ—ˆμ„ λ•Œ μΈμŠ€ν„΄μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€. κ·Έλž˜μ„œ 클래슀 λ©”μ„œλ“œμ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ˜ μ‚¬μš©μ„ κΈˆμ§€ν•œλ‹€.

 

4. λ©”μ„œλ“œ λ‚΄μ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄, static을 λΆ™μ΄λŠ” 것을 κ³ λ €ν•œλ‹€.

 

λ©”μ„œλ“œμ˜ μž‘μ—…λ‚΄μš© μ€‘μ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό ν•„μš”λ‘œ ν•œλ‹€λ©΄, static을 뢙일 수 μ—†λ‹€. λ°˜λŒ€λ‘œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό ν•„μš”λ‘œ ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ static을 λΆ™μ΄μž. λ©”μ„œλ“œ ν˜ΈμΆœμ‹œκ°„μ΄ μ§§μ•„μ§€λ―€λ‘œ μ„±λŠ₯이 ν–₯μƒλœλ‹€. static을 μ•ˆ 뢙인 λ©”μ„œλ“œ(μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ)λŠ” μ‹€ν–‰ μ‹œ ν˜ΈμΆœλ˜μ–΄μ•Ό ν•  λ©”μ„œλ“œλ₯Ό μ°ΎλŠ” 과정이 μΆ”κ°€μ μœΌλ‘œ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ— μ‹œκ°„μ΄ 더 κ±Έλ¦°λ‹€.

 

βœ…μ •λ¦¬

- 클래슀의 멀버 λ³€μˆ˜ 쀑 λͺ¨λ“  μΈμŠ€ν„΄μŠ€μ— κ³΅ν†΅λœ 값을 μœ μ§€ν•΄μ•Ό ν•˜λŠ” 것이 있으면, static을 λΆ™μ—¬μ€€λ‹€.

- μž‘μ„±ν•œ λ©”μ„œλ“œ μ€‘μ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ‚˜ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” λ©”μ„œλ“œμ— static을 뢙일 것을 κ³ λ €ν•œλ‹€.

 

12. 클래슀 멀버와 μΈμŠ€ν„΄μŠ€ 멀버 κ°„μ˜ 참쑰와 호좜

같은 ν΄λž˜μŠ€μ— μ†ν•œ 멀버듀 κ°„μ—λŠ” λ³„λ„μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•Šκ³ λ„ μ„œλ‘œ μ°Έμ‘° λ˜λŠ” 호좜이 κ°€λŠ₯ν•˜λ‹€. 단, 클래슀 멀버가 μΈμŠ€ν„΄μŠ€ 멀버λ₯Ό μ°Έμ‘° λ˜λŠ” ν˜ΈμΆœν•˜κ³ μž ν•˜λŠ” κ²½μš°μ—λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성해야 ν•œλ‹€.

κ·Έ μ΄μœ λŠ” μΈμŠ€ν„΄μŠ€ 멀버가 μ‘΄μž¬ν•˜λŠ” μ‹œμ μ— 클래슀 λ©€λ²„λŠ” 항상 μ‘΄μž¬ν•˜μ§€λ§Œ, 클래슀 멀버가 μ‘΄μž¬ν•˜λŠ” μ‹œμ μ— μΈμŠ€ν„΄μŠ€ 멀버가 μ‘΄μž¬ν•˜μ§€ μ•Šμ„ μˆ˜λ„ 있기 λ•Œλ¬Έμ΄λ‹€.

 

* μΈμŠ€ν„΄μŠ€ λ©€λ²„λž€ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ™€ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ₯Ό μ˜λ―Έν•œλ‹€. 클래슀 λ©€λ²„λž€ 클래슀 λ³€μˆ˜μ™€ 클래슀 μΈμŠ€ν„΄μŠ€λ₯Ό μ˜λ―Έν•œλ‹€.

 

class MemberCall {
    int iv = 10;
    static int cv = 20;

    int iv2 = cv;
    // static int cv2 = iv;         // μ—λŸ¬. 클래슀 λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†μŒ.
    static int cv2 = new MemberCall().iv; // 이처럼 객체λ₯Ό 생성해야 μ‚¬μš©κ°€λŠ₯.

    static void staticMethod1() {
        System.out.println(cv);
        // System.out.println(iv); // μ—λŸ¬. 클래슀 λ©”μ„œλ“œμ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ‚¬μš©λΆˆκ°€.

        MemberCall c = new MemberCall();
        System.out.println(c.iv); // 객체λ₯Ό μƒμ„±ν•œ 후에야 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ˜ μ°Έμ‘°κ°€λŠ₯.
    }

    void instanceMethod1() {
        System.out.println(cv);
        System.out.println(iv); // μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό λ°”λ‘œ μ‚¬μš©κ°€λŠ₯.
    }

    static void staticMethod2() {
        staticMethod1();
        // instanceMethod1() ; // μ—λŸ¬. 클래슀 λ©”μ„œλ“œμ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μ—†μŒ.

        MemberCall c = new MemberCall();
        c.instanceMethod1(); // μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œ 후에야 ν˜ΈμΆœν•  수 있음.
    }

    void instanceMethod2() { // μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ™€ 클래슀 λ©”μ„œλ“œ
        staticMethod2();     // λͺ¨λ‘ μΈμŠ€ν„΄μŠ€ 생성없이 λ°”λ‘œ 호좜이 κ°€λŠ₯ν•˜λ‹€.
        instanceMethod1();
    }
}

클래슀 λ©€λ²„λŠ” μ–Έμ œλ‚˜ μ°Έμ‘° λ˜λŠ” 호좜이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€ 멀버가 클래슀 멀버λ₯Ό μ‚¬μš©ν•˜λŠ” 것은 κ°€λŠ₯ν•˜λ‹€. 클래슀 멀버 κ°„μ˜ μ°Έμ‘° λ˜λŠ” ν˜ΈμΆœλ„ κ°€λŠ₯ν•˜λ‹€. κ·ΈλŸ¬λ‚˜, μΈμŠ€ν„΄μŠ€ λ©€λ²„λŠ” λ°˜λ“œμ‹œ 객체λ₯Ό μƒμ„±ν•œ ν›„μ—λ§Œ μ°Έμ‘° λ˜λŠ” 호좜이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— 클래슀 멀버가 μΈμŠ€ν„΄μŠ€ 멀버λ₯Ό μ°Έμ‘°, ν˜ΈμΆœν•˜κΈ° μœ„ν•΄μ„œλŠ” λ°˜λ“œμ‹œ 객체λ₯Ό 생성해야 ν•œλ‹€.

 

λ˜ν•œ μΈμŠ€ν„΄μŠ€ 멀버 κ°„μ˜ ν˜ΈμΆœλ„ κ°€λŠ₯ν•˜λ‹€. ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€ 멀버가 μ‘΄μž¬ν•œλ‹€λŠ” 것은 μΈμŠ€ν„΄μŠ€κ°€ 이미 μƒμ„±λ˜μ–΄ μžˆλ‹€λŠ” 것을 μ˜λ―Έν•˜λ©°, 즉 λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€ 멀버듀도 λͺ¨λ‘ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. 

 

μ•Œμ•„λ‘λ©΄ μ’‹μ•„μš”!

 

MemberCall c = new MemberCall();
c.instanceMethod1();

 

μœ„μ™€ 같은 두 쀄을 ν•œ μ€„λ‘œ 쀄일 수 μžˆλ‹€.

int result = new MemberCall().instanceMethod1();

λŒ€μ‹  μ°Έμ‘°λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— μƒμ„±λœ MemberCallμΈμŠ€ν„΄μŠ€λŠ” 더 이상 μ‚¬μš©ν•  수 μ—†λ‹€.

 

 

Reference

μžλ°”μ˜ 정석 - 남ꢁ μ„±

λŒ“κΈ€