๐ŸŽฏ1์ฃผ์ฐจ Unit 4.2 โ€” Pass by Value (์ž๋ฐ”์˜ ์ง„์‹ค)

Psjยท6์ผ ์ „

F-lab

๋ชฉ๋ก ๋ณด๊ธฐ
36/52

๐ŸŽฏ Unit 4.2 โ€” Pass by Value (์ž๋ฐ”์˜ ์ง„์‹ค) โ˜…โ˜…โ˜…

F-lab Java 1์ฃผ์ฐจ / Phase 4 / Unit 4.2 ๋ณธ๊ฒฉ ํ•™์Šต ์ž๋ฃŒ
9-์„น์…˜ ๋งˆ์Šคํ„ฐ ํ”„๋กฌํ”„ํŠธ ํ˜•์‹์œผ๋กœ ๊นŠ์ด ํŒŒํ—ค์นœ๋‹ค.

์„ ์ˆ˜ ์ง€์‹: Unit 4.1 (JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ)
๋‹ค์Œ Phase: Phase 5 โ€” GC ๊นŠ์ด ํŒŒ๊ธฐ

์ด Unit์˜ ์˜๋ฏธ: ์ž๋ฐ” ๋ฉด์ ‘์˜ ๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ์˜์—ญ.
"์ž๋ฐ”๋Š” Pass by Reference ๊ฐ€ ์•„๋‹Œ๊ฐ€์š”?" ๋ผ๋Š” ํ”ํ•œ ์˜คํ•ด์˜ ์ง„์‹ค.
๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์œ„์—์„œ ๊ฐ’/์ฐธ์กฐ ์ „๋‹ฌ์˜ ๋ณธ์งˆ์„ ์ดํ•ด.


๐ŸŒ 1. ์„ธ์ƒ ์† ๋น„์œ 

Pass by Value = "์ฃผ์†Œ๊ฐ€ ์ ํžŒ ์ข…์ด์˜ ๋ณต์‚ฌ๋ณธ"

๋‹น์‹ ์ด ์นœ๊ตฌ์—๊ฒŒ ์ง‘ ์ฃผ์†Œ ๋ฅผ ์•Œ๋ ค์ฃผ๋ ค ํ•ฉ๋‹ˆ๋‹ค.

Case 1 โ€” ์ฃผ์†Œ๋ฅผ ์ข…์ด์— ์ ์–ด์คŒ (Pass by Value):

  • ๋‹น์‹ : ์ข…์ด์— "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ..." ์ ์Œ
  • ์นœ๊ตฌ์—๊ฒŒ ์ข…์ด ๋ณต์‚ฌ๋ณธ ์คŒ
  • ์นœ๊ตฌ๊ฐ€ ๊ทธ ์ข…์ด๋ฅผ ์ฐข์–ด๋„ โ†’ ๋‹น์‹ ์˜ ์ข…์ด๋Š” ๊ทธ๋Œ€๋กœ
  • ์นœ๊ตฌ๊ฐ€ ์ข…์ด์— ์ƒˆ ์ฃผ์†Œ ์จ๋„ โ†’ ๋‹น์‹ ๊ณผ ๋ฌด๊ด€

Case 2 โ€” ์นœ๊ตฌ๊ฐ€ ๊ทธ ์ฃผ์†Œ๋กœ ๊ฐ€์„œ ์ง‘์„ ์น ํ•จ (์ฐธ์กฐ์˜ ํ™œ์šฉ):

  • ์นœ๊ตฌ๊ฐ€ ์ข…์ด์— ์ ํžŒ ์ฃผ์†Œ๋กœ ๊ฐ
  • ๊ทธ ์ง‘์˜ ์™ธ๋ฒฝ์„ ๋นจ๊ฐ›๊ฒŒ ์น ํ•จ
  • ๋‹น์‹ ์ด ์ง‘์— ๊ฐ€๋ณด๋ฉด โ†’ ๋นจ๊ฐ„ ์™ธ๋ฒฝ โš ๏ธ
  • ๊ฐ™์€ ์ง‘์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฃผ์†Œ์ด๊ธฐ ๋•Œ๋ฌธ

ํ•ต์‹ฌ:

  • ์ข…์ด(์ฃผ์†Œ) ์ž์ฒด๋Š” ๋ณต์‚ฌ๋ณธ โ†’ ์นœ๊ตฌ๊ฐ€ ์ข…์ด์— ๋ญ๋ผ ์จ๋„ ๋ฌด๊ด€
  • ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ์ฃผ์†Œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹ค์ œ ์ง‘ ์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ โ†’ ์˜ํ–ฅ ์žˆ์Œ

โ†’ ์ด๊ฒŒ ์ž๋ฐ”์˜ Pass by Value ์˜ ์ง„์‹ค.


๋” ์ง๊ด€์ ์ธ ๋น„์œ  โ€” "๋ฆฌ๋ชจ์ปจ ๋ณต์‚ฌ"

๋‹น์‹ ์ด TV ๋ฆฌ๋ชจ์ปจ์„ ์นœ๊ตฌ์—๊ฒŒ ๋นŒ๋ ค์ค€๋‹ค๊ณ  ํ•ฉ์‹œ๋‹ค.

์ง„์งœ ๋ฆฌ๋ชจ์ปจ์„ ๋นŒ๋ ค์คŒ = Pass by Reference (์ž๋ฐ”์— ์—†์Œ):

  • ์นœ๊ตฌ๊ฐ€ ๋ฆฌ๋ชจ์ปจ ๋“ค๊ณ  ๋‹ค๋ฅธ ๋ฐฉ์œผ๋กœ
  • ๋‹น์‹ ์€ TV ๋ชป ์ผฌ

๋ฆฌ๋ชจ์ปจ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ์คŒ = Pass by Value (์ž๋ฐ” ๋ฐฉ์‹):

  • 2๊ฐœ์˜ ๊ฐ™์€ ๋ฆฌ๋ชจ์ปจ
  • ์นœ๊ตฌ๊ฐ€ ์ž๊ธฐ ๋ฆฌ๋ชจ์ปจ์œผ๋กœ TV ๋”
  • โ†’ TV๋Š” ๊บผ์ง (์˜ํ–ฅ ์žˆ์Œ)
  • ์นœ๊ตฌ๊ฐ€ ์ž๊ธฐ ๋ฆฌ๋ชจ์ปจ์„ ๋ถ€์ˆจ โ†’ ๋‹น์‹  ๋ฆฌ๋ชจ์ปจ์€ ๋ฉ€์ฉก

ํ•ต์‹ฌ:

  • ๋‘ ๋ฆฌ๋ชจ์ปจ ๋ชจ๋‘ ๊ฐ™์€ TV ๋ฅผ ๊ฐ€๋ฆฌํ‚ด
  • ๋ฆฌ๋ชจ์ปจ(์ฐธ์กฐ) ์€ ๋ณ„๊ฐœ
  • ๊ทธ๋Ÿฌ๋‚˜ TV(๊ฐ์ฒด)๋Š” ํ•˜๋‚˜ โ†’ ์˜ํ–ฅ ๊ณต์œ 

โ†’ ์ž๋ฐ”์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ์ •ํ™•ํžˆ ์ด ๋ฐฉ์‹.


ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

"์ž๋ฐ”๋Š” ํ•ญ์ƒ Pass by Value ๋‹ค. ๋‹จ, ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ '์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ)' ์ด ๋ณต์‚ฌ๋œ๋‹ค."

์šฉ์–ด ์ •๋ฆฌ:

  • Pass by Value (๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ) โ† ์ž๋ฐ” โœ…
  • Pass by Reference (์ฐธ์กฐ์— ์˜ํ•œ ์ „๋‹ฌ) โ† ์ž๋ฐ”์—๋Š” ์—†์Œ โŒ

ํ”ํ•œ ์˜คํ•ด:

  • "๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋กœ ์ „๋‹ฌ๋˜๋‹ˆ Pass by Reference ์•„๋‹Œ๊ฐ€์š”?"
  • โ†’ NO. ์ฐธ์กฐ(์ฃผ์†Œ) ์˜ ๊ฐ’ ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ.

๋น„์œ  ์ •๋ฆฌ:

๋น„์œ  ์š”์†Œ์ž๋ฐ” ์ ์šฉ
์ข…์ด (์ฃผ์†Œ)์ฐธ์กฐ ๋ณ€์ˆ˜
์ข…์ด์˜ ๋ณต์‚ฌ๋ณธ์ฐธ์กฐ์˜ ๊ฐ’ ๋ณต์‚ฌ
์‹ค์ œ ์ง‘Heap ์˜ ๊ฐ์ฒด
์ง‘ ์น ํ•˜๊ธฐ๊ฐ์ฒด ๋ณ€๊ฒฝ
์ข…์ด ์ฐข๊ธฐ์ฐธ์กฐ ๋ณ€๊ฒฝ (์™ธ๋ถ€ ๋ฌด๊ด€)

๐Ÿ”ฅ 2. ํƒ„์ƒ ๋ฐฐ๊ฒฝ

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ์ธ์ž ์ „๋‹ฌ ๋ฐฉ์‹

์–ธ์–ด๋งˆ๋‹ค ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค:

๋ฐฉ์‹ 1: Pass by Value (๊ฐ’์— ์˜ํ•œ ์ „๋‹ฌ)

  • ์ธ์ž์˜ ๊ฐ’์„ ๋ณต์‚ฌ ํ•ด์„œ ์ „๋‹ฌ
  • ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๋ณ€๊ฒฝํ•ด๋„ ์™ธ๋ถ€ ์˜ํ–ฅ X
  • ์˜ˆ: C ์˜ ๊ธฐ๋ณธ ์ธ์ž ์ „๋‹ฌ
void modify(int x) {
    x = 100;  // ๋ณต์‚ฌ๋œ ๊ฐ’๋งŒ ๋ณ€๊ฒฝ
}
int n = 10;
modify(n);
printf("%d", n);  // 10 (๋ณ€๊ฒฝ ์•ˆ ๋จ)

๋ฐฉ์‹ 2: Pass by Reference (์ฐธ์กฐ์— ์˜ํ•œ ์ „๋‹ฌ)

  • ๋ณ€์ˆ˜ ์ž์ฒด ๋ฅผ ์ „๋‹ฌ (๋ณ„์นญ)
  • ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๋ณ€๊ฒฝํ•˜๋ฉด ์™ธ๋ถ€๋„ ๋ณ€๊ฒฝ
  • ์˜ˆ: C++ ์˜ & ์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜
void modify(int& x) {  // & ์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜
    x = 100;
}
int n = 10;
modify(n);
cout << n;  // 100 โš ๏ธ (๋ณ€๊ฒฝ๋จ)

๋ฐฉ์‹ 3: Pass by Pointer (ํฌ์ธํ„ฐ์— ์˜ํ•œ ์ „๋‹ฌ)

  • ๋ณ€์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์ „๋‹ฌ
  • C ์˜ ๋ช…์‹œ์  ํฌ์ธํ„ฐ
void modify(int* x) {
    *x = 100;
}
int n = 10;
modify(&n);
printf("%d", n);  // 100 (ํฌ์ธํ„ฐ๋กœ ๋ณ€๊ฒฝ)

์ž๋ฐ”์˜ ๊ฒฐ์ • โ€” Pass by Value ๋งŒ โญ

์ž๋ฐ” ์„ค๊ณ„์ž๋“ค์˜ ๊ฒฐ์ • (1995):

"์ž๋ฐ”๋Š” Pass by Value ๋งŒ ์ง€์›ํ•œ๋‹ค. ๋‹จ, ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋กœ ๋‹ค๋ฃฌ๋‹ค."

์™œ?:

  • ๋‹จ์ˆœํ•จ (ํ•œ ๊ฐ€์ง€ ๋ฐฉ์‹๋งŒ)
  • ์•ˆ์ „ (์˜ˆ์ธก ๊ฐ€๋Šฅ)
  • ๊ฐ์ฒด๋Š” ์–ด์ฐจํ”ผ ์ฐธ์กฐ๋กœ ์ฒ˜๋ฆฌ๋˜๋‹ˆ ๋ณ„๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ถˆํ•„์š”

"์ž๋ฐ”๋Š” Pass by Reference" ์˜คํ•ด์˜ ๋“ฑ์žฅ

๊ทธ๋Ÿฌ๋‚˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ํ—ท๊ฐˆ๋ฆฝ๋‹ˆ๋‹ค:

public void modify(Customer c) {
    c.setName("Bob");  // โš ๏ธ ๋ณ€๊ฒฝ๋จ!
}

Customer alice = new Customer("Alice");
modify(alice);
System.out.println(alice.getName());  // "Bob" โ€” ๋ณ€๊ฒฝ๋จ!

์˜คํ•ด:

  • "์–ด? ๋ณ€๊ฒฝ๋˜๋„ค? ๊ทธ๋Ÿผ Pass by Reference ์•„๋‹Œ๊ฐ€?"

์ง„์‹ค:

  • ์ž๋ฐ”๋Š” ์—ฌ์ „ํžˆ Pass by Value
  • ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ
  • ๋‘ ์ฐธ์กฐ๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ด
  • ๊ฐ์ฒด ๋ณ€๊ฒฝ โ†’ ์–‘์ชฝ ๋ชจ๋‘ ์˜ํ–ฅ

โ†’ ์ด ํ•จ์ •์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๋Š” ๊ฒŒ ์‹œ๋‹ˆ์–ด ์ž๋ฐ” ๊ฐœ๋ฐœ์ž์˜ ์ฐจ๋ณ„ํ™”.


James Gosling (์ž๋ฐ” ์ฐฝ์‹œ์ž) ์˜ ์ธ์šฉ

์ž๋ฐ” ์ฐฝ์‹œ์ž James Gosling์€ ๋ช…์‹œ์ ์œผ๋กœ ๋งํ•จ:

"Java has no pass by reference. Everything is pass by value."
("์ž๋ฐ”๋Š” Pass by Reference๊ฐ€ ์—†๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด Pass by Value ๋‹ค.")

โ†’ ์ž๋ฐ” ๊ณต์‹ ์ž…์žฅ.


๋ฉด์ ‘์—์„œ์˜ ํ•จ์ • โš ๏ธ

๋ฉด์ ‘ ๋‹จ๊ณจ ์งˆ๋ฌธ:

"์ž๋ฐ”๋Š” Pass by Value ์ธ๊ฐ€ Pass by Reference ์ธ๊ฐ€?"

์ž˜๋ชป๋œ ๋‹ต:

  • "๊ธฐ๋ณธํ˜•์€ Value, ๊ฐ์ฒด๋Š” Reference ์ž…๋‹ˆ๋‹ค" โŒ

์˜ฌ๋ฐ”๋ฅธ ๋‹ต:

  • "์ž๋ฐ”๋Š” ํ•ญ์ƒ Pass by Value ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค." โœ…

โ†’ ์ด ๋‹ต์œผ๋กœ ์‹œ๋‹ˆ์–ด ํ›„๋ณด ์ฐจ๋ณ„ํ™”.


ํ•ต์‹ฌ ํ†ต์ฐฐ

"Pass by Value ์˜ ์ง„์‹ค์€ 'JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ' ์œ„์—์„œ ๋ช…ํ™•ํ•ด์ง„๋‹ค."

Stack์—๋Š” ๋ณ€์ˆ˜์˜ ๊ฐ’ (๊ธฐ๋ณธํ˜•์€ ๊ฐ’ ์ž์ฒด, ๊ฐ์ฒด๋Š” ์ฐธ์กฐ = ์ฃผ์†Œ), Heap์—๋Š” ๊ฐ์ฒด. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ Stack์˜ ๊ฐ’ ์ด ๋ณต์‚ฌ๋˜์–ด ์ƒˆ Stack Frame ์œผ๋กœ. ๊ทธ๋ž˜์„œ ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ ๋‘ ์ฐธ์กฐ๊ฐ€ ๊ฐ™์€ Heap ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ด.

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ (Unit 4.1) ๋ฅผ ๋ชจ๋ฅด๋ฉด Pass by Value ๋„ ์ง„์งœ ์ดํ•ด ๋ชป ํ•จ.


๐Ÿ’ฃ 3. ์—†์œผ๋ฉด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

Pass by Value์˜ ์ง„์‹ค์„ ๋ชจ๋ฅด๋ฉด ๋‹ค์–‘ํ•œ ๋ฒ„๊ทธ์™€ ํ˜ผ๋ž€์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์‹œ๋‚˜๋ฆฌ์˜ค 1: ๊ฐ์ฒด ๋ณ€๊ฒฝ์˜ ์˜์™ธ์„ฑ

public class FareService {
    public void applyDiscount(Fare fare, int rate) {
        int discount = fare.getAmount() * rate / 100;
        fare.setAmount(fare.getAmount() - discount);
    }
}

Fare myFare = new Fare(50000);
fareService.applyDiscount(myFare, 20);

System.out.println(myFare.getAmount());  // 40000? 50000?

Pass by Value ์ง„์‹ค ๋ชจ๋ฅด๋ฉด:

  • "๊ฐ’์œผ๋กœ ์ „๋‹ฌ๋์œผ๋‹ˆ 50000 ๊ทธ๋Œ€๋กœ ์•„๋‹Œ๊ฐ€?"
  • โ†’ ๋‹ต์€ 40000 โš ๏ธ

Pass by Value ์ง„์‹ค ์•Œ๋ฉด:

  • myFare ์˜ ์ฐธ์กฐ ๊ฐ’ (์ฃผ์†Œ) ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ
  • ๋‘ ์ฐธ์กฐ (myFare ์™€ fare) ๊ฐ€ ๊ฐ™์€ Heap ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • ๊ฐ์ฒด ๋ณ€๊ฒฝ โ†’ ์–‘์ชฝ ๋ชจ๋‘ ๋ณด์ž„
  • โ†’ 40000

์‹œ๋‚˜๋ฆฌ์˜ค 2: ๊ฐ์ฒด ๊ต์ฒด ์‹œ๋„

public class FareService {
    public void replace(Fare fare) {
        fare = new Fare(10000);  // ์ƒˆ ๊ฐ์ฒด๋กœ ๊ต์ฒด ์‹œ๋„
    }
}

Fare myFare = new Fare(50000);
fareService.replace(myFare);

System.out.println(myFare.getAmount());  // 50000? 10000?

Pass by Reference ๋ผ๊ณ  ์˜คํ•ดํ•˜๋ฉด:

  • "10000์œผ๋กœ ๊ต์ฒด๋๊ฒ ์ง€"

์ง„์‹ค (Pass by Value):

  • ๋ฉ”์„œ๋“œ ์•ˆ์˜ fare = myFare ์˜ ์ฐธ์กฐ ๋ณต์‚ฌ๋ณธ
  • fare = new Fare(10000) โ†’ ๋ฉ”์„œ๋“œ ์•ˆ์˜ fare ๋งŒ ์ƒˆ ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • myFare ๋Š” ์—ฌ์ „ํžˆ 50000 ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • โ†’ 50000

๋ฉ”๋ชจ๋ฆฌ ๋ณ€ํ™”:

ํ˜ธ์ถœ ์งํ›„:
[Stack โ€” main]
  myFare โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚
[Stack โ€” replace]            
  fare โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
              โ”‚
[Heap]        โ–ผ
  Fare(50000)

fare = new Fare(10000) ํ›„:
[Stack โ€” main]
  myFare โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚
[Stack โ€” replace]
  fare โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚
[Heap]        โ–ผ          โ–ผ
  Fare(50000)  Fare(10000)  โ† ์ƒˆ ๊ฐ์ฒด

๋ฉ”์„œ๋“œ ์ข…๋ฃŒ ํ›„:
[Stack โ€” main]
  myFare โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚
[Heap]        โ–ผ
  Fare(50000)  Fare(10000)
                โ† GC ๋Œ€์ƒ (์ฐธ์กฐ X)

โ†’ ๊ฐ์ฒด ๊ต์ฒด๋Š” Pass by Value ๋กœ ์•ˆ ๋จ.


์‹œ๋‚˜๋ฆฌ์˜ค 3: ํ”ํ•œ ๋ฒ„๊ทธ โ€” ๋ฐ˜ํ™˜์„ ๊นœ๋นก

// โŒ ์ž˜๋ชป๋œ ์ฝ”๋“œ
public void increment(Integer count) {
    count = count + 1;  // ์™ธ๋ถ€ ์˜ํ–ฅ ์—†์Œ
}

Integer myCount = 10;
increment(myCount);
System.out.println(myCount);  // 10 (๋ณ€๊ฒฝ ์•ˆ ๋จ)

์™œ?:

  • Integer ๋Š” ๊ฐ์ฒด์ด์ง€๋งŒ ๋ถˆ๋ณ€ (immutable)
  • count = count + 1 โ†’ ์ƒˆ Integer ๊ฐ์ฒด ๋งŒ๋“ค์–ด ๋ฉ”์„œ๋“œ ์•ˆ์˜ count์— ํ• ๋‹น
  • ์›๋ณธ myCount ๋ฌด๊ด€

ํ•ด๊ฒฐ โ€” ๋ฐ˜ํ™˜ ์‚ฌ์šฉ:

public Integer increment(Integer count) {
    return count + 1;
}

Integer myCount = 10;
myCount = increment(myCount);  // โ† ๋ฐ˜ํ™˜๋ฐ›์•„์„œ
System.out.println(myCount);   // 11 โœ…

์‹œ๋‚˜๋ฆฌ์˜ค 4: List ์ •๋ ฌ์˜ ์˜์™ธ์„ฑ

public void sort(List<Integer> list) {
    list.sort(Comparator.naturalOrder());  // ์ •๋ ฌ
}

List<Integer> myList = new ArrayList<>(List.of(3, 1, 2));
sort(myList);
System.out.println(myList);  // [3, 1, 2]? [1, 2, 3]?

์ง„์‹ค: [1, 2, 3] โš ๏ธ

์™œ?:

  • list ๋Š” myList ์˜ ์ฐธ์กฐ ๋ณต์‚ฌ
  • ๊ฐ™์€ ArrayList ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • list.sort() โ†’ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ
  • โ†’ ์–‘์ชฝ์—์„œ ๋ณด์ž„

โ†’ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์™ธ๋ถ€ ์˜ํ–ฅ.


์‹œ๋‚˜๋ฆฌ์˜ค 5: ๋งค๊ฐœ๋ณ€์ˆ˜ ์žฌํ• ๋‹น ์‹œ ํ—ท๊ฐˆ๋ฆผ

public void process(List<Integer> list) {
    list.add(100);              // ์™ธ๋ถ€ ์˜ํ–ฅ โœ…
    list = new ArrayList<>();   // ์žฌํ• ๋‹น
    list.add(200);              // ์™ธ๋ถ€ ์˜ํ–ฅ X
}

List<Integer> myList = new ArrayList<>(List.of(1, 2, 3));
process(myList);
System.out.println(myList);  // ?

๋‹ต: [1, 2, 3, 100]

์™œ?:
1. list.add(100) โ€” ๊ฐ™์€ ๊ฐ์ฒด ๋ณ€๊ฒฝ โ†’ myList ์—๋„ 100 ์ถ”๊ฐ€
2. list = new ArrayList<>() โ€” ๋ฉ”์„œ๋“œ ์•ˆ์˜ list๋งŒ ์ƒˆ ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด, myList ๋ฌด๊ด€
3. list.add(200) โ€” ์ƒˆ ๊ฐ์ฒด์—๋งŒ ์ถ”๊ฐ€, myList ๋ฌด๊ด€

โ†’ ์žฌํ• ๋‹น ์ „ํ›„์˜ ๋™์ž‘์ด ์™„์ „ํžˆ ๋‹ค๋ฆ„.


์‹œ๋‚˜๋ฆฌ์˜ค 6: ๋ฉด์ ‘ ํƒˆ๋ฝ

"์ž๋ฐ”๋Š” Pass by Value ์ธ๊ฐ€์š” Pass by Reference ์ธ๊ฐ€์š”?"

๋‹ต ๋ชปํ•จ ๋˜๋Š” ํ—ท๊ฐˆ๋ฆผ:

  • "์Œ... ๊ฐ์ฒด๋Š” reference ๊ฐ™์€๋ฐ..."
  • โ†’ ์‹œ๋‹ˆ์–ด ์ž๊ฒฉ ๋…ธ์ถœ

์ž˜ ๋‹ตํ•จ:

  • "์ž๋ฐ”๋Š” ํ•ญ์ƒ Pass by Value ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ฐธ์กฐ์˜ ๊ฐ’ ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋‘ ์ฐธ์กฐ๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ์€ ์–‘์ชฝ์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค."
  • โ†’ ์ •ํ™•ํ•œ ์ดํ•ด ํ‘œํ˜„

โœ… 4. ํ•ด๊ฒฐ์ฑ… โ€” Pass by Value ์˜ ์ •ํ™•ํ•œ ์ดํ•ด

ํ•ต์‹ฌ ๊ทœ์น™ โญ

์ž๋ฐ”์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์€ ๋‹ค์Œ ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

๊ทœ์น™ 1: ๊ธฐ๋ณธํ˜• (primitive) โ€” ๊ฐ’ ์ž์ฒด๊ฐ€ ๋ณต์‚ฌ

public void modify(int x) {
    x = 100;
}

int n = 10;
modify(n);
System.out.println(n);  // 10

๋ฉ”๋ชจ๋ฆฌ:

ํ˜ธ์ถœ ์งํ›„:
[Stack โ€” main]
  n = 10
[Stack โ€” modify]
  x = 10  โ† ๊ฐ’ ๋ณต์‚ฌ

x = 100 ํ›„:
[Stack โ€” main]
  n = 10  โ† ๊ทธ๋Œ€๋กœ
[Stack โ€” modify]
  x = 100  โ† ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ๋ณ€๊ฒฝ

โ†’ ๊ฐ’ ๋ณต์‚ฌ. ์™ธ๋ถ€ ๋ฌด๊ด€.


๊ทœ์น™ 2: ๊ฐ์ฒด โ€” ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ์ด ๋ณต์‚ฌ

public void modify(Customer c) {
    c.setName("Bob");  // ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ
}

Customer alice = new Customer("Alice");
modify(alice);
System.out.println(alice.getName());  // "Bob"

๋ฉ”๋ชจ๋ฆฌ:

ํ˜ธ์ถœ ์งํ›„:
[Stack โ€” main]
  alice (์ฐธ์กฐ = 0x1234)
              โ”‚
[Stack โ€” modify]    โ”‚
  c (์ฐธ์กฐ = 0x1234) โ”€โ”ค  โ† ๊ฐ™์€ ์ฃผ์†Œ
              โ”‚
[Heap]        โ–ผ
  Customer ("Alice")  ์ฃผ์†Œ 0x1234

c.setName("Bob") ํ›„:
[Stack โ€” main]
  alice (์ฐธ์กฐ = 0x1234)
              โ”‚
[Stack โ€” modify]    โ”‚
  c (์ฐธ์กฐ = 0x1234) โ”€โ”ค
              โ”‚
[Heap]        โ–ผ
  Customer ("Bob")  โ† ๊ฐ์ฒด ์ž์ฒด ๋ณ€๊ฒฝ

โ†’ ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ์ด ๋ณต์‚ฌ. ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ ๋ณ€๊ฒฝ ๊ณต์œ .


๊ทœ์น™ 3: ๊ฐ์ฒด ์žฌํ• ๋‹น โ€” ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ์˜ํ–ฅ

public void modify(Customer c) {
    c = new Customer("Bob");  // ์žฌํ• ๋‹น
}

Customer alice = new Customer("Alice");
modify(alice);
System.out.println(alice.getName());  // "Alice" (๋ณ€๊ฒฝ ์•ˆ ๋จ)

๋ฉ”๋ชจ๋ฆฌ:

ํ˜ธ์ถœ ์งํ›„:
[Stack โ€” main]
  alice (์ฐธ์กฐ = 0x1234)
              โ”‚
[Stack โ€” modify]    โ”‚
  c (์ฐธ์กฐ = 0x1234) โ”€โ”ค
              โ”‚
[Heap]        โ–ผ
  Customer ("Alice")  ์ฃผ์†Œ 0x1234

c = new Customer("Bob") ํ›„:
[Stack โ€” main]
  alice (์ฐธ์กฐ = 0x1234)
              โ”‚
[Stack โ€” modify]
  c (์ฐธ์กฐ = 0x5678)  โ† ์ƒˆ ์ฃผ์†Œ
              โ”‚
[Heap]        โ–ผ              โ–ผ
  Customer ("Alice")  Customer ("Bob")  ์ฃผ์†Œ 0x5678
                      โ† c๋งŒ ๊ฐ€๋ฆฌํ‚ด

๋ฉ”์„œ๋“œ ์ข…๋ฃŒ ํ›„:
[Stack โ€” main]
  alice (์ฐธ์กฐ = 0x1234)
              โ”‚
[Heap]        โ–ผ              โ–ผ
  Customer ("Alice")  Customer ("Bob")
                      โ† GC ๋Œ€์ƒ (์ฐธ์กฐ X)

โ†’ ์žฌํ• ๋‹น = ๋ฉ”์„œ๋“œ ์•ˆ์˜ ๋ณ€์ˆ˜๋งŒ ๋ณ€๊ฒฝ. ์™ธ๋ถ€ ๋ฌด๊ด€.


๊ฒฐ๋ก  โ€” ํ•œ ํ‘œ๋กœ ์ •๋ฆฌ โญโญ (๋ฉด์ ‘ ๋‹ต๋ณ€ ํ•ต์‹ฌ)

์ผ€์ด์Šค๋ฉ”์„œ๋“œ ์•ˆ ๋ณ€๊ฒฝ์™ธ๋ถ€ ์˜ํ–ฅ
๊ธฐ๋ณธํ˜• ๋ณ€๊ฒฝ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ๋ณ€๊ฒฝX
๊ฐ์ฒด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ (c.setName())๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝO โš ๏ธ
๊ฐ์ฒด ์žฌํ• ๋‹น (c = new ...)๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ์ƒˆ ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ดX
๋ถˆ๋ณ€ ๊ฐ์ฒด ๋ณ€๊ฒฝ ์‹œ๋„ (Integer + 1)์ƒˆ ๊ฐ์ฒด ๋งŒ๋“ค์–ด ์žฌํ• ๋‹นX

โ†’ ์ด ํ‘œ๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์œผ๋ฉด ์ž๋ฐ” ๋ฉด์ ‘ OK.


ํ•จ์ˆ˜ํ˜• ์ธ์ž ์ „๋‹ฌ (Java 8+)

Java 8 ๋žŒ๋‹ค๋„ ๊ฐ™์€ ๊ทœ์น™:

public void process(Function<Integer, Integer> func) {
    int result = func.apply(10);
}

process(x -> x * 2);  // ๋žŒ๋‹ค ์ž์ฒด๊ฐ€ ๊ฐ์ฒด๋กœ ์ „๋‹ฌ

โ†’ ๋žŒ๋‹ค๋„ ๊ฐ์ฒด โ†’ ์ฐธ์กฐ์˜ ๊ฐ’ ๋ณต์‚ฌ.


์˜๋„์ ์œผ๋กœ ์™ธ๋ถ€ ๋ณ€๊ฒฝ โ€” Wrapper ํŒจํ„ด

๊ธฐ๋ณธํ˜•์„ ๋ฉ”์„œ๋“œ์—์„œ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด:

// โŒ ์•ˆ ๋จ
public void increment(int x) {
    x++;
}

// โœ… Wrapper ์‚ฌ์šฉ
public void increment(int[] arr) {
    arr[0]++;  // ๋ฐฐ์—ด์€ ๊ฐ์ฒด
}

int[] count = {0};
increment(count);
System.out.println(count[0]);  // 1

// โœ… ๋˜๋Š” AtomicInteger
public void increment(AtomicInteger count) {
    count.incrementAndGet();
}

AtomicInteger count = new AtomicInteger(0);
increment(count);
System.out.println(count.get());  // 1

โ†’ ๊ฐ์ฒด๋กœ ๊ฐ์‹ธ์„œ ์ฐธ์กฐ์˜ ๊ฐ’ ๋ณต์‚ฌ ํ™œ์šฉ.

๊ทธ๋Ÿฌ๋‚˜ โ€” ๋ณดํ†ต ๋ฐ˜ํ™˜ ์‚ฌ์šฉ ์ด ๋” ๊น”๋”:

public int increment(int x) {
    return x + 1;
}

int n = 10;
n = increment(n);

ํ•ต์‹ฌ ์ •๋ฆฌ โ€” ๋ฉด์ ‘์šฉ 5๋ถ„ ๋‹ต๋ณ€ ๊ตฌ์กฐ

์งˆ๋ฌธ: "์ž๋ฐ”๋Š” Pass by Value ์ธ๊ฐ€ Pass by Reference ์ธ๊ฐ€?"

๋‹ต๋ณ€ ๊ตฌ์กฐ:

  1. ๊ฒฐ๋ก  (10์ดˆ): "์ž๋ฐ”๋Š” ํ•ญ์ƒ Pass by Value ์ž…๋‹ˆ๋‹ค."

  2. ๊ธฐ๋ณธํ˜• ์„ค๋ช… (30์ดˆ):

    • "๊ธฐ๋ณธํ˜•์€ ๊ฐ’ ์ž์ฒด๊ฐ€ ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค."
    • ์˜ˆ์‹œ ์ฝ”๋“œ ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ.
  3. ๊ฐ์ฒด ์„ค๋ช… (1๋ถ„):

    • "๊ฐ์ฒด๋„ Pass by Value ์ธ๋ฐ, ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ์ด ๋ณต์‚ฌ ๋ฉ๋‹ˆ๋‹ค."
    • "๊ทธ๋ž˜์„œ ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ ์‹œ ์™ธ๋ถ€์— ์˜ํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค."
    • "๊ทธ๋Ÿฌ๋‚˜ ๊ฐ์ฒด๋ฅผ ์žฌํ• ๋‹นํ•˜๋ฉด ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค."
  4. ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ (1๋ถ„):

    • Stack ์˜ ๋ณ€์ˆ˜, Heap ์˜ ๊ฐ์ฒด, ์ฐธ์กฐ ๊ด€๊ณ„ ์„ค๋ช….
  5. ํ”ํ•œ ์˜คํ•ด (30์ดˆ):

    • "Pass by Reference ์™€ ํ—ท๊ฐˆ๋ฆฌ๊ธฐ ์‰ฌ์šด๋ฐ, James Gosling ๋„ ๋ช…์‹œ์ ์œผ๋กœ 'Java has no pass by reference' ๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค."
  6. ์‹ค์šฉ์  ํ•จ์˜ (1๋ถ„):

    • "๊ทธ๋ž˜์„œ ๊ฐ์ฒด๋ฅผ ๋ฉ”์„œ๋“œ์— ๋„˜๊ธธ ๋•Œ ๋ถ€์ˆ˜ํšจ๊ณผ ์— ์ฃผ์˜ํ•ด์•ผ ํ•˜๊ณ , ๋ณ€๊ฒฝ ๊ฒฐ๊ณผ๋ฅผ ์™ธ๋ถ€์— ๋ฐ˜์˜ํ•˜๋ ค๋ฉด ๋ฐ˜ํ™˜ ์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค."

โ†’ ์ด ๊ตฌ์กฐ๋ฉด ์‹œ๋‹ˆ์–ด ๋‹ต๋ณ€.


๐Ÿ—๏ธ 5. ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ณ€ํ™” (์ž์„ธํžˆ)

public class Demo {
    public static void main(String[] args) {
        int x = 10;
        Customer c = new Customer("Alice");
        
        process(x, c);
        
        System.out.println(x);            // ?
        System.out.println(c.getName());  // ?
    }
    
    public static void process(int n, Customer cust) {
        n = 100;
        cust.setName("Bob");
    }
}

Step 1 โ€” main ์‹œ์ž‘:

[Method Area]
  Demo ํด๋ž˜์Šค ์ •๋ณด, Customer ํด๋ž˜์Šค ์ •๋ณด
  
[Heap]
  (์•„์ง ๋น„์–ด์žˆ์Œ)
  
[Stack โ€” main]
  args (์ฐธ์กฐ)
  x (์•„์ง ๋ฏธํ• ๋‹น)
  c (์•„์ง ๋ฏธํ• ๋‹น)

Step 2 โ€” int x = 10:

[Stack โ€” main]
  args
  x = 10        โ† Stack ์— ์ง์ ‘ ๊ฐ’ ์ €์žฅ
  c

Step 3 โ€” Customer c = new Customer("Alice"):

[Heap]
  Customer ์ธ์Šคํ„ด์Šค ("Alice")  ์ฃผ์†Œ 0x1234
       โ†‘
[Stack โ€” main]
  args
  x = 10
  c = 0x1234    โ† ์ฐธ์กฐ (์ฃผ์†Œ) ์ €์žฅ

Step 4 โ€” process(x, c) ํ˜ธ์ถœ:

[Heap]
  Customer ("Alice")  0x1234
       โ†‘
       โ”‚
[Stack โ€” main]
  args
  x = 10
  c = 0x1234 โ”€โ”€โ”
                โ”‚
[Stack โ€” process] (์ƒˆ Frame)
  n = 10        โ† x์˜ ๊ฐ’ ๋ณต์‚ฌ
  cust = 0x1234 โ”€โ”€โ”˜ โ† c์˜ ๊ฐ’(์ฃผ์†Œ) ๋ณต์‚ฌ

Step 5 โ€” n = 100:

[Stack โ€” main]
  x = 10        โ† ๊ทธ๋Œ€๋กœ
  
[Stack โ€” process]
  n = 100       โ† ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ๋ณ€๊ฒฝ

Step 6 โ€” cust.setName("Bob"):

[Heap]
  Customer ("Bob")  โ† ๊ฐ์ฒด ์ž์ฒด ๋ณ€๊ฒฝ
       โ†‘       โ†‘
       โ”‚       โ”‚
[Stack โ€” main]
  c = 0x1234 โ”€โ”€โ”˜
              โ”‚
[Stack โ€” process]
  n = 100
  cust = 0x1234 โ”€โ”€โ”˜
              โ†‘ ๊ฐ™์€ ์ฃผ์†Œ ๊ฐ€๋ฆฌํ‚ด

Step 7 โ€” process ์ข…๋ฃŒ:

[Stack โ€” main]
  c = 0x1234 โ”€โ”€โ”
                โ”‚
                โ–ผ
[Heap]
  Customer ("Bob")  โ† ๋ณ€๊ฒฝ๋จ

(process Frame ์ œ๊ฑฐ)

์ตœ์ข… ์ถœ๋ ฅ:

  • System.out.println(x) โ†’ 10 (๋ฉ”์„œ๋“œ ์•ˆ ๋ณ€๊ฒฝ ๋ฌด๊ด€)
  • System.out.println(c.getName()) โ†’ "Bob" (๊ฐ์ฒด ๋ณ€๊ฒฝ๋จ)

์ฐธ์กฐ (Reference) vs ํฌ์ธํ„ฐ (Pointer)

์ž๋ฐ”์˜ ์ฐธ์กฐ์™€ C์˜ ํฌ์ธํ„ฐ์˜ ์ฐจ์ด:

C ํฌ์ธํ„ฐJava ์ฐธ์กฐ
๋ช…์‹œ์ int* p๋ชจ๋“  ๊ฐ์ฒด ๋ณ€์ˆ˜
์‚ฐ์ˆ  ์—ฐ์‚ฐ๊ฐ€๋Šฅ (p++)๋ถˆ๊ฐ€
null ์ฒดํฌ์ž๋™ X์ž๋™ (NPE)
๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์œ„ํ—˜์•ˆ์ „
์ง์ ‘ ์ฃผ์†Œ ๋ณด๊ธฐprintf("%p", p)๋ถˆ๊ฐ€

โ†’ ์ž๋ฐ” ์ฐธ์กฐ = "์•ˆ์ „ํ•œ ํฌ์ธํ„ฐ".


== vs .equals() ์˜ ์ง„์งœ ์˜๋ฏธ โญ

String a = new String("hello");
String b = new String("hello");

a == b;          // false
a.equals(b);     // true

์™œ?:

  • == ๋Š” ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ๋น„๊ต
  • .equals() ๋Š” ๊ฐ์ฒด ๋‚ด์šฉ ๋น„๊ต

๋ฉ”๋ชจ๋ฆฌ:

[Heap]
  String ("hello")  ์ฃผ์†Œ 0x1111
  String ("hello")  ์ฃผ์†Œ 0x2222

[Stack]
  a = 0x1111
  b = 0x2222
  • a == b โ†’ 0x1111 == 0x2222 โ†’ false
  • a.equals(b) โ†’ ๋‚ด์šฉ "hello" == "hello" โ†’ true

๊ธฐ๋ณธํ˜• ๋น„๊ต:

int x = 10;
int y = 10;
x == y;  // true (๊ฐ’ ๋น„๊ต)

โ†’ ๊ธฐ๋ณธํ˜•์˜ == ๋Š” ๊ฐ’, ๊ฐ์ฒด์˜ == ๋Š” ์ฐธ์กฐ.


Integer Cache ์˜ ํ•จ์ • โš ๏ธ

Integer a = 100;
Integer b = 100;
a == b;  // true โš ๏ธ

Integer c = 200;
Integer d = 200;
c == d;  // false โš ๏ธ

์™œ?:

  • Java๋Š” -128 ~ 127 ๋ฒ”์œ„ Integer ๋ฅผ ์บ์‹œ ํ•จ
  • 100, 100 โ†’ ์บ์‹œ์—์„œ ๊ฐ™์€ ๊ฐ์ฒด โ†’ ๊ฐ™์€ ์ฐธ์กฐ
  • 200, 200 โ†’ ์ƒˆ ๊ฐ์ฒด โ†’ ๋‹ค๋ฅธ ์ฐธ์กฐ

ํ•ด๊ฒฐ: ํ•ญ์ƒ equals() ์‚ฌ์šฉ:

a.equals(b);  // true (์•ˆ์ „)
c.equals(d);  // true

โ†’ ์ž๋ฐ” ๋ฉด์ ‘ ํ•จ์ • ์งˆ๋ฌธ.


String Pool ๊ณผ Pass by Value

String a = "hello";
String b = "hello";
a == b;  // true!

String c = new String("hello");
a == c;  // false

์™œ?:

  • ๋ฆฌํ„ฐ๋Ÿด "hello" ๋Š” String Pool (Method Area ๋˜๋Š” Heap์˜ ํŠน๋ณ„ ์˜์—ญ) ์— ์ €์žฅ
  • ๊ฐ™์€ ๋ฆฌํ„ฐ๋Ÿด โ†’ ๊ฐ™์€ ์ฐธ์กฐ
  • new String() โ†’ Heap ์— ์ƒˆ ๊ฐ์ฒด โ†’ ๋‹ค๋ฅธ ์ฐธ์กฐ

โ†’ Unit 6์—์„œ ์ž์„ธํžˆ.


๐Ÿ’ป 6. ์‹ค์ „ ์ฝ”๋“œ ์˜ˆ์‹œ

์˜ˆ์‹œ 1: ILIC ์šด์ž„ ๋ณ€๊ฒฝ์˜ ๋ถ€์ˆ˜ํšจ๊ณผ

@Service
public class FareUpdateService {
    
    public void applyDiscount(Fare fare, int rate) {
        int discount = fare.getAmount() * rate / 100;
        fare.setAmount(fare.getAmount() - discount);
        // โš ๏ธ ์™ธ๋ถ€ fare ๋„ ๋ณ€๊ฒฝ๋จ
    }
}

@Service
public class CheckoutService {
    private final FareUpdateService updateService;
    
    public Fare checkout(Long fareId) {
        Fare fare = fareRepository.findById(fareId).orElseThrow();
        
        // ์˜๋„: ์ž„์‹œ ํ• ์ธ ์ ์šฉ ํ›„ ์˜์ˆ˜์ฆ ์ถœ๋ ฅ
        updateService.applyDiscount(fare, 20);
        
        return fare;
        // โš ๏ธ DB ์˜ fare ๋„ ์˜ํ–ฅ?
        // โ†’ JPA ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ํ•ด ๋ณ€๊ฒฝ ๊ฐ์ง€ โ†’ DB UPDATE
    }
}

๋ถ€์ˆ˜ํšจ๊ณผ ์œ„ํ—˜:

  • fare ๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์žˆ์Œ
  • applyDiscount ๊ฐ€ ๊ฐ์ฒด ๋ณ€๊ฒฝ
  • ํŠธ๋žœ์žญ์…˜ ์ข…๋ฃŒ ์‹œ ์ž๋™ UPDATE โ†’ ์˜๋„ํ•˜์ง€ ์•Š์€ DB ๋ณ€๊ฒฝ

ํ•ด๊ฒฐ:

public Fare calculateDiscountedFare(Fare fare, int rate) {
    int discountedAmount = fare.getAmount() * (100 - rate) / 100;
    return new Fare(discountedAmount);  // ์ƒˆ ๊ฐ์ฒด ๋ฐ˜ํ™˜
}

โ†’ ๋ถˆ๋ณ€์„ฑ + ๋ฐ˜ํ™˜ ์„ ํ™œ์šฉ.


์˜ˆ์‹œ 2: ๋ฐฐ์—ด์˜ Pass by Value

public class ArrayDemo {
    public void modify(int[] arr) {
        arr[0] = 100;          // ์™ธ๋ถ€ ์˜ํ–ฅ โœ…
        arr = new int[]{1, 2}; // ์™ธ๋ถ€ ์˜ํ–ฅ X
    }
    
    public static void main(String[] args) {
        int[] myArr = {10, 20, 30};
        new ArrayDemo().modify(myArr);
        
        System.out.println(Arrays.toString(myArr));
        // [100, 20, 30] โš ๏ธ
    }
}

์™œ?:

  • arr[0] = 100 โ†’ Heap ์˜ ๋ฐฐ์—ด ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ โ†’ ์™ธ๋ถ€์—์„œ ๋ณด์ž„
  • arr = new int[]{...} โ†’ ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ ์ƒˆ ๋ฐฐ์—ด ๊ฐ€๋ฆฌํ‚ด

๋ฉ”๋ชจ๋ฆฌ:

ํ˜ธ์ถœ ์งํ›„:
[Heap]
  int[] {10, 20, 30}  ์ฃผ์†Œ 0x1234
       โ†‘
[Stack โ€” main]
  myArr = 0x1234 โ”€โ”€โ”
                    โ”‚
[Stack โ€” modify]    โ”‚
  arr = 0x1234 โ”€โ”€โ”€โ”€โ”€โ”˜

arr[0] = 100 ํ›„:
[Heap]
  int[] {100, 20, 30}  โ† ๋ณ€๊ฒฝ

arr = new int[]{1, 2} ํ›„:
[Heap]
  int[] {100, 20, 30}  โ† myArr ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด
  int[] {1, 2}  ์ฃผ์†Œ 0x5678 โ† arr ๋งŒ ๊ฐ€๋ฆฌํ‚ด

์˜ˆ์‹œ 3: List ๋ณ€๊ฒฝ

public void process(List<Integer> list) {
    list.add(100);              // ์™ธ๋ถ€ ์˜ํ–ฅ โœ…
    list.remove(0);             // ์™ธ๋ถ€ ์˜ํ–ฅ โœ…
    list.set(0, 999);           // ์™ธ๋ถ€ ์˜ํ–ฅ โœ…
    
    list = new ArrayList<>();   // ์™ธ๋ถ€ ์˜ํ–ฅ X
    list.add(200);              // ์™ธ๋ถ€ ์˜ํ–ฅ X
}

List<Integer> myList = new ArrayList<>(List.of(1, 2, 3));
process(myList);
System.out.println(myList);  // ?

์ง„ํ–‰ ๋‹จ๊ณ„:
1. ์‹œ์ž‘: [1, 2, 3]
2. add(100) โ†’ [1, 2, 3, 100] (์™ธ๋ถ€ ์˜ํ–ฅ)
3. remove(0) โ†’ [2, 3, 100] (์™ธ๋ถ€ ์˜ํ–ฅ)
4. set(0, 999) โ†’ [999, 3, 100] (์™ธ๋ถ€ ์˜ํ–ฅ)
5. list = new ArrayList<>() โ†’ ๋ฉ”์„œ๋“œ ์•ˆ์˜ list๋งŒ, myList ๊ทธ๋Œ€๋กœ
6. list.add(200) โ†’ ์ƒˆ ๊ฐ์ฒด์—๋งŒ, myList ๋ฌด๊ด€

์ตœ์ข…: [999, 3, 100]


์˜ˆ์‹œ 4: ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์•ˆ์ „์„ฑ

public void process(String s) {
    s = s + "!";  // ์ƒˆ String ๊ฐ์ฒด ์ƒ์„ฑ
}

String myStr = "hello";
process(myStr);
System.out.println(myStr);  // "hello"

์™œ ๋ณ€๊ฒฝ ์•ˆ ๋จ?:

  • String ์€ ๋ถˆ๋ณ€ (immutable)
  • s + "!" โ†’ ์ƒˆ String ๊ฐ์ฒด ์ƒ์„ฑ, s ์— ์žฌํ• ๋‹น
  • ๋ฉ”์„œ๋“œ ์•ˆ์˜ s ๋งŒ ์ƒˆ ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • myStr ๋ฌด๊ด€

๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์žฅ์ :

  • Pass by Value ์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ์—†์Œ
  • ์•ˆ์ „
  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์— ์•ˆ์ „

ILIC ์ ์šฉ:

public class FareSnapshot {  // ๋ถˆ๋ณ€
    private final Long id;
    private final int amount;
    private final FareStatus status;
    
    // setter ์—†์Œ
    // ๋ณ€๊ฒฝ ์‹œ ์ƒˆ ๊ฐ์ฒด ๋ฐ˜ํ™˜
    public FareSnapshot withAmount(int newAmount) {
        return new FareSnapshot(id, newAmount, status);
    }
}

โ†’ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๋ถ€์ˆ˜ํšจ๊ณผ ๋ฐฉ์ง€.


์˜ˆ์‹œ 5: ์˜๋„์  ๋ณ€๊ฒฝ โ€” Wrapper ํ™œ์šฉ

public class Counter {
    private int value;
    
    public Counter(int value) { this.value = value; }
    public void increment() { value++; }
    public int getValue() { return value; }
}

public void process(Counter counter) {
    counter.increment();
}

Counter myCounter = new Counter(0);
process(myCounter);
process(myCounter);
process(myCounter);
System.out.println(myCounter.getValue());  // 3

ํ•ต์‹ฌ:

  • Counter ๋Š” ๊ฐ€๋ณ€ ๊ฐ์ฒด
  • ๋ฉ”์„œ๋“œ์—์„œ increment() ํ˜ธ์ถœ โ†’ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ โ†’ ์™ธ๋ถ€์—์„œ ๋ณด์ž„
  • ์˜๋„์ ์œผ๋กœ ์™ธ๋ถ€ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

โ†’ Wrapper ํŒจํ„ด.

๋” ๋‚˜์€ ๋ฐฉ๋ฒ• โ€” AtomicInteger (์Šค๋ ˆ๋“œ ์•ˆ์ „):

AtomicInteger counter = new AtomicInteger(0);

public void process(AtomicInteger counter) {
    counter.incrementAndGet();
}

์˜ˆ์‹œ 6: ๋ณต์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ โ€” Defensive Copy

public class Order {
    private final List<Item> items;
    
    public Order(List<Item> items) {
        // ๋ฐฉ์–ด์  ๋ณต์‚ฌ โ€” ์™ธ๋ถ€ ๋ณ€๊ฒฝ์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธ
        this.items = new ArrayList<>(items);
    }
    
    public List<Item> getItems() {
        // ๋ฐฉ์–ด์  ๋ณต์‚ฌ โ€” ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ ๋ชปํ•˜๊ฒŒ
        return new ArrayList<>(items);
        // ๋˜๋Š” Collections.unmodifiableList(items);
    }
}

List<Item> myItems = new ArrayList<>();
myItems.add(new Item("A"));
Order order = new Order(myItems);

myItems.add(new Item("B"));  // ์™ธ๋ถ€์—์„œ ์ถ”๊ฐ€
order.getItems();  // [Item("A")] โ€” ์˜ํ–ฅ ์—†์Œ โœ…

์™œ?:

  • ๋‹จ์ˆœํžˆ this.items = items ํ•˜๋ฉด ์™ธ๋ถ€ ๋ณ€๊ฒฝ์— ์˜ํ–ฅ ๋ฐ›์Œ
  • new ArrayList<>(items) ๋กœ ์ƒˆ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ
  • โ†’ ์™ธ๋ถ€ ๋ณ€๊ฒฝ ๊ฒฉ๋ฆฌ

โ†’ Effective Java ์˜ ๊ถŒ์žฅ ํŒจํ„ด.


โš ๏ธ 7. ์ฃผ์˜์‚ฌํ•ญ & ํ”ํ•œ ์‹ค์ˆ˜

์‹ค์ˆ˜ 1: "๊ฐ์ฒด๋Š” Pass by Reference" ๋ผ๊ณ  ํ•จ

Q: "๊ฐ์ฒด๋ฅผ ๋ฉ”์„œ๋“œ์— ๋„˜๊ธฐ๋ฉด?"
A: "Pass by Reference ์ž…๋‹ˆ๋‹ค" โŒ

์ •๋‹ต: Pass by Value โ€” ์ฐธ์กฐ์˜ ๊ฐ’ ๋ณต์‚ฌ.


์‹ค์ˆ˜ 2: == ๋กœ ๊ฐ์ฒด ๋น„๊ต

String a = new String("hello");
String b = new String("hello");
if (a == b) { ... }  // โŒ false ๋‚˜์˜ด

ํ•ด๊ฒฐ: .equals() ์‚ฌ์šฉ:

if (a.equals(b)) { ... }  // โœ…

โ†’ ๊ฐ์ฒด ๋น„๊ต๋Š” ํ•ญ์ƒ equals().


์‹ค์ˆ˜ 3: ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฐ์ฒด ๋ณ€๊ฒฝ

@Service
public class FareService {
    public void process(Fare fare) {
        fare.setStatus(FareStatus.PROCESSING);
        // โš ๏ธ ํ˜ธ์ถœ์ž์˜ fare ๋„ ์˜ํ–ฅ
    }
}

Fare myFare = repository.findById(1L).orElseThrow();
service.process(myFare);
// myFare ์˜ status ๋„ ๋ณ€๊ฒฝ๋จ
// ํŠธ๋žœ์žญ์…˜ ์•ˆ์ด๋ฉด DB UPDATE๊นŒ์ง€!

ํ•ด๊ฒฐ: ์˜๋„๋ฅผ ๋ช…ํ™•ํžˆ ๋˜๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด:

public Fare process(Fare fare) {
    return new Fare(fare.getId(), fare.getAmount(), FareStatus.PROCESSING);
}

์‹ค์ˆ˜ 4: Integer ๋น„๊ต

Integer a = 200;
Integer b = 200;
if (a == b) { ... }  // โš ๏ธ false (์บ์‹œ ๋ฒ”์œ„ ๋ฐ–)

ํ•ด๊ฒฐ: ํ•ญ์ƒ equals():

if (a.equals(b)) { ... }  // โœ…

๋˜๋Š” ๊ธฐ๋ณธํ˜• ์‚ฌ์šฉ:

int a = 200;
int b = 200;
if (a == b) { ... }  // โœ… true

์‹ค์ˆ˜ 5: ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ

public void process(int count) {
    count = count + 1;  // โŒ ์˜๋ฏธ X
    // count ๋ณ€๊ฒฝํ•ด๋„ ์™ธ๋ถ€ ์˜ํ–ฅ ์—†์Œ
}

ํ•ด๊ฒฐ: ๋ฐ˜ํ™˜:

public int process(int count) {
    return count + 1;
}

์‹ค์ˆ˜ 6: List ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ƒˆ List ํ• ๋‹น

public void clear(List<Integer> list) {
    list = new ArrayList<>();  // โŒ ์™ธ๋ถ€ list ์•ˆ ๋น„์›Œ์ง
}

ํ•ด๊ฒฐ:

public void clear(List<Integer> list) {
    list.clear();  // โœ… ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
}

์‹ค์ˆ˜ 7: ๋ณต์‚ฌ ์—†์ด ์™ธ๋ถ€ ๋ณ€๊ฒฝ ํ—ˆ์šฉ

public class Order {
    private List<Item> items;
    
    public Order(List<Item> items) {
        this.items = items;  // โŒ ์™ธ๋ถ€ list ์™€ ๊ณต์œ 
    }
    
    public List<Item> getItems() {
        return items;  // โŒ ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
    }
}

ํ•ด๊ฒฐ: ๋ฐฉ์–ด์  ๋ณต์‚ฌ:

this.items = new ArrayList<>(items);
return Collections.unmodifiableList(items);

๐Ÿ”— 8. ์—ฐ๊ด€ ๊ฐœ๋… ๋งต

Phase 4 (JVM ๋ฉ”๋ชจ๋ฆฌ) ์™„์„ฑ

[Unit 4.1: JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ]
        โ†“
[Unit 4.2: Pass by Value] โ† ์ง€๊ธˆ ์—ฌ๊ธฐ โ˜…
        โ†“
[Phase 4 ์™„๋ฃŒ]

โ†’ Phase 4 ์™„๋ฃŒ. ๋‹ค์Œ์€ Phase 5 GC.


Phase 1-3๊ณผ์˜ ํ†ตํ•ฉ

ํ•™์ŠตPass by Value ๊ด€์ 
Unit 1.1 (๊ฐ์ฒด์ง€ํ–ฅ)๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋กœ ๋‹ค๋ฃธ (Pass by Value)
Unit 2.1 (๋ฉ”์„œ๋“œ)๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ์ธ์ž ๋ณต์‚ฌ
Unit 2.4 (๋‹คํ˜•์„ฑ)์ฐธ์กฐ์˜ ํƒ€์ž…๊ณผ ์‹ค์ œ ๊ฐ์ฒด ๊ตฌ๋ถ„
Unit 4.1 (JVM ๋ฉ”๋ชจ๋ฆฌ)Stack/Heap ์œ„์—์„œ ๋™์ž‘

โ†’ Pass by Value ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ ์œ„์—์„œ ์ดํ•ด.


๋ฏธ๋ž˜ ์ฃผ์ฐจ์™€์˜ ์—ฐ๊ฒฐ

3์ฃผ์ฐจ (์ œ๋„ค๋ฆญ/๋žŒ๋‹ค):

  • ๋žŒ๋‹ค๋„ ๊ฐ์ฒด โ†’ Pass by Value
  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋ถˆ๋ณ€์„ฑ ๊ฐ•์กฐ

4์ฃผ์ฐจ (๋™์‹œ์„ฑ):

  • ๊ณต์œ  ๊ฐ์ฒด์˜ ์œ„ํ—˜ (Heap ์˜ ๊ฐ์ฒด)
  • volatile, synchronized

5์ฃผ์ฐจ (Spring DI):

  • Bean ๋“ค์˜ ์ฐธ์กฐ ์ฃผ์ž…

11-12์ฃผ์ฐจ (JPA):

  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๊ฐ์ฒด ๊ด€๋ฆฌ
  • Dirty Checking โ€” ๊ฐ์ฒด ๋ณ€๊ฒฝ ์ž๋™ ๊ฐ์ง€

Effective Java ์˜ ๊ถŒ์žฅ:

  • ๋ถˆ๋ณ€ ๊ฐ์ฒด ์„ ํ˜ธ
  • ๋ฐฉ์–ด์  ๋ณต์‚ฌ
  • โ†’ Pass by Value ์ดํ•ด์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฒฐ๊ณผ

๋ฉด์ ‘ ๋‹จ๊ณจ ์งˆ๋ฌธ ๋งคํ•‘

์งˆ๋ฌธ์ด Unit์—์„œ์˜ ๋‹ต
"์ž๋ฐ”๋Š” Pass by Value? Reference?"ํ•ญ์ƒ Pass by Value, ๊ฐ์ฒด๋Š” ์ฐธ์กฐ์˜ ๊ฐ’ ๋ณต์‚ฌ
"๊ฐ์ฒด๋ฅผ ๋ฉ”์„œ๋“œ์—์„œ ๋ณ€๊ฒฝ ์‹œ ์™ธ๋ถ€ ์˜ํ–ฅ?"๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ ์‹œ ์˜ํ–ฅ, ์žฌํ• ๋‹น์€ X
"== ์™€ equals() ์ฐจ์ด?"== ๋Š” ์ฐธ์กฐ (๊ฐ์ฒด) ๋˜๋Š” ๊ฐ’ (๊ธฐ๋ณธํ˜•) ๋น„๊ต, equals() ๋Š” ๋‚ด์šฉ
"Integer ๋น„๊ต ํ•จ์ •?"-128~127 ์บ์‹œ, ๊ทธ ์™ธ ๋‹ค๋ฅธ ๊ฐ์ฒด
"๋ฐฉ์–ด์  ๋ณต์‚ฌ๊ฐ€ ๋ญ”๊ฐ€์š”?"Pass by Value ์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ๋ฐฉ์ง€

๐Ÿ“ 9. ํ•ต์‹ฌ ์š”์•ฝ โ€” 3์ค„ ์ •๋ฆฌ

1๏ธโƒฃ ์ž๋ฐ”๋Š” ํ•ญ์ƒ Pass by Value ๋‹ค โ€” ๊ฐ์ฒด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€.

James Gosling ๋„ ๋ช…์‹œ: "Java has no pass by reference." ๊ธฐ๋ณธํ˜•์€ ๊ฐ’ ์ž์ฒด ๋ณต์‚ฌ, ๊ฐ์ฒด๋Š” ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ) ๋ณต์‚ฌ. ๋‘˜ ๋‹ค Stack ์˜ ๊ฐ’์„ ์ƒˆ Stack Frame ์— ๋ณต์‚ฌํ•˜๋Š” ๋ฐฉ์‹. ์ด ์‚ฌ์‹ค์€ JVM ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ (Unit 4.1) ์œ„์—์„œ ๋ช…ํ™•ํ•ด์ง„๋‹ค.

2๏ธโƒฃ ๊ฐ์ฒด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ vs ์žฌํ• ๋‹น โ€” ๊ฒฐ๊ณผ๊ฐ€ ์™„์ „ํžˆ ๋‹ค๋ฅด๋‹ค.

๋ฉ”์„œ๋“œ์—์„œ c.setName("Bob") ๊ฐ™์€ ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ ์€ ์™ธ๋ถ€์— ์˜ํ–ฅ โญ (๊ฐ™์€ Heap ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋‘ ์ฐธ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ). ๋ฐ˜๋ฉด c = new Customer() ๊ฐ™์€ ์žฌํ• ๋‹น ์€ ๋ฉ”์„œ๋“œ ์•ˆ์˜ ๋ณ€์ˆ˜๋งŒ ์ƒˆ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌ์ผœ ์™ธ๋ถ€ ๋ฌด๊ด€. ์ด ๊ตฌ๋ถ„์ด ์ž๋ฐ” ๋ฉด์ ‘์˜ ๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆฌ๋Š” ์˜์—ญ.

3๏ธโƒฃ ๋ถˆ๋ณ€ ๊ฐ์ฒด์™€ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋กœ ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ํ†ต์ œํ•˜๋ผ.

Pass by Value ์˜ ๊ฐ์ฒด ๋ณ€๊ฒฝ ์˜ํ–ฅ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด: โ‘  ๋ถˆ๋ณ€ ๊ฐ์ฒด ์‚ฌ์šฉ (String, Integer ์ฒ˜๋Ÿผ ๋ณ€๊ฒฝ ์‹œ ์ƒˆ ๊ฐ์ฒด), โ‘ก ๋ฐฉ์–ด์  ๋ณต์‚ฌ (์ƒ์„ฑ์ž/getter ์—์„œ ์ƒˆ ์ปฌ๋ ‰์…˜ ์ƒ์„ฑ), โ‘ข ๋ฐ˜ํ™˜ ๊ฐ’ ํ™œ์šฉ (๋ณ€๊ฒฝ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์„œ ๋ช…์‹œ์  ํ• ๋‹น). Effective Java ๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ํŒจํ„ด๋“ค โ€” ๋ชจ๋‘ Pass by Value ์˜ ํ•จ์ • ํšŒํ”ผ.


๐ŸŽ“ ํ•™์Šต ์ž๊ธฐ ์ ๊ฒ€

๊ธฐ๋ณธ ์ดํ•ด

  • ์ž๋ฐ”๊ฐ€ Pass by Value ์ž„์„ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ "์ฐธ์กฐ์˜ ๊ฐ’" ์ด ๋ณต์‚ฌ๋œ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ์•ˆ๋‹ค
  • ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ vs ์žฌํ• ๋‹น์˜ ์ฐจ์ด๋ฅผ ๊ตฌ๋ณ„ํ•œ๋‹ค
  • == ์™€ equals() ์˜ ๋ณธ์งˆ์  ์ฐจ์ด๋ฅผ ์•ˆ๋‹ค

์‹ค์ „ ์ ์šฉ

  • ILIC ์ฝ”๋“œ์˜ ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฐ์ฒด ๋ณ€๊ฒฝ์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด ํŒจํ„ด์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค
  • Integer ๋น„๊ต ํ•จ์ •์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค

๋ฉด์ ‘ ๋Œ€๋น„ (5๋ถ„ ๋‹ต๋ณ€)

  • "์ž๋ฐ”๋Š” Pass by Value?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ์œผ๋กœ ์„ค๋ช… ๊ฐ€๋Šฅ
  • == ์™€ equals() ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • Integer ์บ์‹œ ๋‹ต๋ณ€ ๊ฐ€๋Šฅ

์ž๊ธฐ ์ ๊ฒ€ ์งˆ๋ฌธ ๋‹ต๋ณ€

Q1: ์ž๋ฐ”์—๋Š” ์ •๋ง Pass by Reference๊ฐ€ ์—†๋Š”๊ฐ€?

ํ•œ ์ค„ ๋‹ต: YES, ์ ˆ๋Œ€ ์—†๋‹ค. James Gosling ๋„ ๋ช…์‹œ.

์ƒ์„ธ ์„ค๋ช…:

์ž๋ฐ”๋Š” ๋ชจ๋“  ์ธ์ž๋ฅผ ๊ฐ’์œผ๋กœ ์ „๋‹ฌ:

  • ๊ธฐ๋ณธํ˜• โ†’ ๊ฐ’ ์ž์ฒด ๋ณต์‚ฌ
  • ๊ฐ์ฒด โ†’ ์ฐธ์กฐ์˜ ๊ฐ’ (์ฃผ์†Œ) ๋ณต์‚ฌ

Pass by Reference ๋ผ๋ฉด (์ž๋ฐ”์— ์—†๋Š” ๊ฒƒ):

// ๊ฐ€์ƒ โ€” ์ž๋ฐ”์— ์ด๋Ÿฐ ๋ฌธ๋ฒ• ์—†์Œ
public void modify(Customer& c) {  // & ์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜ (C++)
    c = new Customer("Bob");  // ์™ธ๋ถ€๋„ ์ƒˆ ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
}

Customer alice = new Customer("Alice");
modify(alice);
// alice ๊ฐ€ ์ƒˆ Customer("Bob") ๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ Pass by Reference
// โ†’ ์ž๋ฐ”์—์„œ๋Š” ๋ถˆ๊ฐ€๋Šฅ

์ž๋ฐ”์˜ ์‹ค์ œ (Pass by Value):

public void modify(Customer c) {
    c = new Customer("Bob");  // ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ
}

Customer alice = new Customer("Alice");
modify(alice);
System.out.println(alice.getName());  // "Alice" โ€” ๋ณ€๊ฒฝ ์•ˆ ๋จ

โ†’ Pass by Reference ๋ผ๋ฉด "Bob" ์ด ๋‚˜์™€์•ผ ํ•จ. ๊ทธ๋Ÿฐ๋ฐ ์•ˆ ๋‚˜์˜ด โ†’ Pass by Reference ๊ฐ€ ์•„๋‹˜.

์™œ ํ—ท๊ฐˆ๋ฆฌ๋‚˜?:

  • ๊ฐ์ฒด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ (c.setName("Bob")) ์€ ์™ธ๋ถ€์— ์˜ํ–ฅ
  • ์ด๊ฒƒ์„ "Reference๋กœ ์ „๋‹ฌ๋ผ์„œ" ๋ผ๊ณ  ์˜คํ•ด
  • โ†’ ์‚ฌ์‹ค์€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋‘ ์ฐธ์กฐ ๋•Œ๋ฌธ

๋น„์œ :

  • ๋‘ ์‚ฌ๋žŒ์ด ๊ฐ™์€ ์ง‘ ์ฃผ์†Œ ๋ฅผ ์ ์€ ์ข…์ด๋ฅผ ๊ฐ€์ง
  • ํ•œ ์‚ฌ๋žŒ์ด ๊ทธ ์ง‘์„ ์น ํ•จ โ†’ ๋‘˜ ๋‹ค ๊ทธ ์ง‘์„ ๋ณด๋ฉด ์น ํ•ด์ง„ ์ƒ‰
  • ๊ทธ๋Ÿฌ๋‚˜ ์ข…์ด(์ฃผ์†Œ) ์ž์ฒด๋Š” ๋ณ„๊ฐœ
  • โ†’ ์ž๋ฐ” ๊ฐ์ฒด ์ „๋‹ฌ๊ณผ ์ •ํ™•ํžˆ ๋™์ผ

Q2: ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•๊ณผ ๊ฐ์ฒด ์ž๋ฃŒํ˜•์˜ ๋ฉ”์„œ๋“œ ์ธ์ž ์ „๋‹ฌ ์ฐจ์ด๋Š”?

ํ•œ ์ค„ ๋‹ต: ๋‘˜ ๋‹ค Pass by Value, ๋‹จ ๋ณต์‚ฌ๋˜๋Š” ๋Œ€์ƒ ์ด ๋‹ค๋ฆ„.

์ƒ์„ธ ์„ค๋ช…:

๊ธฐ๋ณธ ์ž๋ฃŒํ˜• (primitive)

public void modify(int x) {
    x = 100;
}

int n = 10;
modify(n);
System.out.println(n);  // 10

๋ณต์‚ฌ ๋Œ€์ƒ: ๊ฐ’ ์ž์ฒด (10)

๋ฉ”๋ชจ๋ฆฌ:

[Stack โ€” main]
  n = 10
[Stack โ€” modify]
  x = 10  โ† ๊ฐ’ ๋ณต์‚ฌ

ํšจ๊ณผ: ๋ฉ”์„œ๋“œ ์•ˆ ๋ณ€๊ฒฝ โ†’ ์™ธ๋ถ€ ๋ฌด๊ด€.


๊ฐ์ฒด ์ž๋ฃŒํ˜• (Reference)

public void modify(Customer c) {
    c.setName("Bob");
}

Customer alice = new Customer("Alice");
modify(alice);
System.out.println(alice.getName());  // "Bob"

๋ณต์‚ฌ ๋Œ€์ƒ: ์ฐธ์กฐ์˜ ๊ฐ’(์ฃผ์†Œ)

๋ฉ”๋ชจ๋ฆฌ:

[Heap]
  Customer ("Alice")  ์ฃผ์†Œ 0x1234
       โ†‘       โ†‘
       โ”‚       โ”‚
[Stack โ€” main]    [Stack โ€” modify]
  alice = 0x1234   c = 0x1234   โ† ๊ฐ™์€ ์ฃผ์†Œ

ํšจ๊ณผ: ๋‘ ์ฐธ์กฐ๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด โ†’ ๊ฐ์ฒด ๋ณ€๊ฒฝ ์‹œ ์–‘์ชฝ ์˜ํ–ฅ.


๊ฒฐ์ •์  ์ฐจ์ด ํ‘œ โญ

์ธก๋ฉด๊ธฐ๋ณธํ˜•๊ฐ์ฒด
๋ณต์‚ฌ ๋Œ€์ƒ๊ฐ’ ์ž์ฒด์ฐธ์กฐ์˜ ๊ฐ’ (์ฃผ์†Œ)
๋ฉ”์„œ๋“œ ์•ˆ ๋ณ€๊ฒฝ ์‹œ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ณ€๊ฒฝ โ†’ ์™ธ๋ถ€ ์˜ํ–ฅ
์žฌํ• ๋‹น ์‹œ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ๋ฉ”์„œ๋“œ ์•ˆ๋งŒ
๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜Stack ์— ์ง์ ‘์ฐธ์กฐ๋Š” Stack, ๊ฐ์ฒด๋Š” Heap

ํ•ต์‹ฌ ํ†ต์ฐฐ โญ :

"๋‘˜ ๋‹ค Pass by Value ์ธ๋ฐ, '๊ฐ’' ์˜ ์˜๋ฏธ๊ฐ€ ๋‹ค๋ฅด๋‹ค.
๊ธฐ๋ณธํ˜•์˜ ๊ฐ’ = ์‹ค์ œ ๋ฐ์ดํ„ฐ, ๊ฐ์ฒด์˜ ๊ฐ’ = ์ฐธ์กฐ(์ฃผ์†Œ)"

์‹œ๊ฐํ™”:

๊ธฐ๋ณธํ˜•:
  [๋ณต์‚ฌ๋˜๋Š” ๊ฒƒ]: โ—โ—โ—โ—โ—  (์‹ค์ œ ๋ฐ์ดํ„ฐ)

๊ฐ์ฒด:
  [๋ณต์‚ฌ๋˜๋Š” ๊ฒƒ]: โ†’ โ†’ โ†’ โ†’ โ†’  (์ฃผ์†Œ๋งŒ)
                  โ†“
              ์‹ค์ œ ๊ฐ์ฒด (Heap, 1๊ฐœ)

โ†’ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ (Unit 4.1) ์œ„์—์„œ ๋ช…ํ™•ํ•ด์ง.


Phase 4 ์™„๋ฃŒ โ€” ๋‹ค์Œ์œผ๋กœ

  • Phase 5 (GC) ํ•™์Šต ์ค€๋น„ ์™„๋ฃŒ
  • Heap ์˜ ๊ฐ์ฒด๊ฐ€ ์–ด๋–ป๊ฒŒ ์ˆ˜๊ฑฐ๋˜๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค
  • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€๋ฅผ ๋งŒ๋‚  ์ค€๋น„ ์™„๋ฃŒ

๐ŸŽ‰ Phase 4 ์™„๋ฃŒ ์ถ•ํ•˜!

ํ•™์Šตํ•œ 2๊ฐœ Unit

Unit์ฃผ์ œํ•ต์‹ฌ
4.1JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ โ˜…โ˜…โ˜…5๊ฐ€์ง€ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ
4.2Pass by Value โ˜…โ˜…โ˜…์ž๋ฐ”์˜ ์ธ์ž ์ „๋‹ฌ ์ง„์‹ค

Phase 4์˜ ํ•ต์‹ฌ ํ†ต์ฐฐ

"๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ์ž๋ฐ”๋ฅผ ์ง„์งœ ์ดํ•ดํ•œ ๊ฒƒ์ด๋‹ค."

Pass by Value, ๋™์‹œ์„ฑ, GC, JPA ์˜์†์„ฑ โ€” ๋ชจ๋“  ์ž๋ฐ”์˜ ๊นŠ์€ ์ฃผ์ œ๊ฐ€ ์ด ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ ์œ„์— ์„œ ์žˆ๋‹ค. ์ถ”์ƒ์˜ ์„ธ๊ณ„ (Phase 1-3) ์™€ ๋ฌผ๋ฆฌ์˜ ์„ธ๊ณ„ (Phase 4) ๊ฐ€ ๋งŒ๋‚˜๋Š” ์ง€์ .

Phase 5 ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ€” GC ๊นŠ์ด ํŒŒ๊ธฐ

์ด์ œ Heap ์˜ ๊ฐ์ฒด๊ฐ€ ์–ด๋–ป๊ฒŒ ์ˆ˜๊ฑฐ๋˜๋Š”์ง€:

  • Mark-Sweep, Mark-Compact, Generational
  • Young/Old Generation
  • G1, ZGC ๋“ฑ ํ˜„๋Œ€ GC
  • GC ํŠœ๋‹๊ณผ ๋ชจ๋‹ˆํ„ฐ๋ง

โ†’ Heap ์ดํ•ด (Unit 4.1) ๊ฐ€ ๊ฒฐ์ •์  ํ† ๋Œ€.

profile
Software Developer

0๊ฐœ์˜ ๋Œ“๊ธ€