Early Binding๊ณผ Late Binding์€ ์„ฑ๋Šฅ์—์„œ ์–ด๋–ค ์ฐจ์ด๊ฐ€ ๋‚˜๋Š”๊ฐ€? ์‹ค์ œ๋กœ๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€? ์•Œ๊ฒŒ ๋ชจ๋ฅด๊ฒŒ ๋‹น์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋‹คํ˜•์  ๋ฉ”์„œ๋“œ๋Š” ๋ฌด์—‡์ด ์žˆ์„๊นŒ?

์ด๋ฅธ ๋ฐ”์ธ๋”ฉ vs. ๋Šฆ์€ ๋ฐ”์ธ๋”ฉ - ์„ฑ๋Šฅ์  ์ธก๋ฉด

  • ๋‹น์—ฐํžˆ ์ด๋ฅธ ๋ฐ”์ธ๋”ฉ์ด CPU ์ตœ์ ํ™” ๊ฐ€๋Šฅ์„ฑ์ด ๋” ๋†’๋‹ค.
  • ์ฆ‰, ๋‚˜์€ ์„ฑ๋Šฅ์„ ๊ฐ€์ ธ์˜ฌ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.
  • ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ๊ณ ,
  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ์ค‘์— ์ถฉ๋ถ„ํ•œ ์‹œ๊ฐ„์„ ๊ฐ€์ง€๊ณ  ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์‹คํ–‰์ค‘์—๋Š” ์ด๋ ‡๊ฒŒ ์ถฉ๋ถ„ํ•œ ์‹œ๊ฐ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
  • ๋นŒ๋“œ ์‹œ๊ฐ„์€ ์˜ค๋ž˜ ๊ฑธ๋ ค๋„ ์ƒ๊ด€์—†๋‹ค. ๋‹ค๋งŒ, ์‹คํ–‰์‹œ์— ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š” ๊ฒƒ์€ ์–˜๊ธฐ๊ฐ€ ๋‹ค๋ฅด๋‹ค.

๋‹คํ˜•์„ฑ ์ง€์› ์–ธ์–ด์—์„œ์˜ ์ด๋ฅธ ๋ฐ”์ธ๋”ฉ

  • ์ผ๋‹จ์€ ๊ฐ ์–ธ์–ด์˜ compiler์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ๊ฐ ์–ธ์–ด ํŠน์„ฑ์— ๋”ฐ๋ผ ๊ณต๋ถ€ํ•ด๋ณด์•„์•ผ ํ•œ๋‹ค.
  • final ํ‚ค์›Œ๋“œ๋ฅผ ๋‹ฌ๋ฉด, ์ด๋ฅธ ๋ฐ”์ธ๋”ฉ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

final keyword

โ€œ๋”์ด์ƒ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์–ด. ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ•ดโ€

  • ์ž์‹์—์„œ override ๋ถˆ๊ฐ€
  • ์ด๋ฅธ ๋ฐ”์ธ๋”ฉ์ด ๊ฐ€๋Šฅ
  • ์ •ํ™•ํ•œ ๋‚ด์šฉ์€ ๊ฐ ์–ธ์–ด์˜ ์ŠคํŽ™์„ ํ™•์ธํ•  ๊ฒƒ. ๋‹ค๋งŒ, ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ด๋ฏ€๋กœ ๊ทธ๋ ‡๊ฒŒ ๋™์ž‘ํ•  ๊ฒƒ
  • Swift์˜ ๊ฒฝ์šฐ์—๋Š” โ€œMethod Dispatchโ€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ดํŽด๋ณด๋ฉด ๋„์›€์ด ๋œ๋‹ค.

final์˜ ์˜๋ฏธ

final์— ์–ด๊ธ‹๋‚˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋ชจ๋‘ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜

  • ๋ณ€์ˆ˜ ์•ž
    • ๋”์ด์ƒ ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Œ
    • public final int MAX_STUDENT = 10
  • ํด๋ž˜์Šค ์•ž
    • ๋”์ด์ƒ ์ƒ์† ๋ถˆ๊ฐ€
    • ์ž์‹ ํด๋ž˜์Šค ์กด์žฌํ•  ์ˆ˜ ์—†์Œ
    • ์˜ค๋ฒ„๋ผ์ด๋”ฉ๋„ ๋‹น์—ฐํžˆ ๋ถˆ๊ฐ€
  • ๋ฉ”์„œ๋“œ ์•ž
    • ์ž์‹ ํด๋ž˜์Šค์—์„œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์—†์Œ
  • ํŒŒ๋ผ๋ฏธํ„ฐ ์•ž
    • ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์€ ์ผ์„ ํ•  ์ˆ˜ ์—†๋‹ค.
    • ๋‚ด๋ถ€์—์„œ ์žฌํ• ๋‹น์„ ๋ง‰๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
public void save(final Person person) {
   person = new Person();
    entityManager.persist(person);
}

final Best Practice

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

Object์˜ ๋‹คํ˜•์  ๋ฉ”์„œ๋“œ

  • ์•„๋ฌด์ƒ๊ฐ ์—†์ด ์‚ฌ์šฉํ–ˆ๋˜ ๋ฉ”์„œ๋“œ๋“ค์ด ์–ด๋””์— ์žˆ์—ˆ์„๊นŒ?
  • ์ผ๋ฐ˜ํ™”์˜ ๋ํŒ์™•, Object์— ์žˆ๋‹ค.
  • Java์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  Calss๋Š” ๋ชจ๋‘ Object์—์„œ ์ƒ์†๋ฐ›๋Š”๋‹ค.
  • ๊ทธ๋ ‡๊ธฐ์— Object์— ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋“ค์€ ์–ด๋–ค ํด๋ž˜์Šค์—์„œ๋„ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ž์ฃผ ์“ฐ์ด๋Š” ๋ฉ”์„œ๋“œ๋“ค ๋ช‡๊ฐœ๋งŒ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

toString()

  • ํ•ด๋‹น ๊ฐœ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ํ‘œํ˜„ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ
  • ๊ธฐ๋ณธ๊ตฌํ˜„: getClass().getName() + '@' + Integer.toHexString(hashCode())
    • hashCode()๋Š” ๋’ค์—์„œ ์•Œ์•„๋ณด์ž.
  • String ๊ฒฝ์šฐ์—๋Š” ๋‚ด์šฉ๋ฌผ์„ ๋ณด์—ฌ์ฃผ๋Š”๊ฒŒ ์ข‹์œผ๋‹ˆ ์ด๋Ÿฐ ๊ฒฝ์šฐ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.
  • ์‚ฌ์‹ค ๊ณต์‹ ๋ฌธ์„œ์—๋Š” ์ด ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋“  ํด๋ž˜์Šค์—์„œ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋ผ๊ณ  ๊ถŒ์žฅํ•˜๊ธฐ๋Š” ํ•œ๋‹ค.
    • ๊ทผ๋ฐ ์ž˜ ์•ˆํ•œ๋‹ค..

equals()

  • ๋ฌด์—‡์ด ๊ฐ™์€ ๊ฒƒ์ด๋ผ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?
  • ๊ฐœ๋…์ ์œผ๋กœ(๋‚ด์šฉ)? ๋ฌผ๋ฆฌ์ ์œผ๋กœ(์ฃผ์†Œ)?, ์–ด๋А ์ •๋„ ์ง‘ํ•ฉ ๊นŠ์ด์—์„œ ๊ฐ™๋‹ค๊ณ  ์ •์˜ํ•ด์•ผ ํ•˜๋Š”๊ฐ€?
  • ์ด๊ฑด ๋งŒ๋“œ๋Š” ๋†ˆ์ด ์ •์˜ํ•  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.
  • ๊ธฐ๋ณธ ๊ตฌํ˜„: ๋‹จ์ˆœํ•œ ์ฃผ์†Œ ๋น„๊ต (this == obj)
    • ๋ฐ์ดํ„ฐ๋ฅผ ์ผ์ผํžˆ ๋น„๊ตํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ์ปดํ“จํ„ฐ ์ž…์žฅ์—์„œ๋Š” ์ด ์ •์˜๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋งž๋Š” ๊ฒƒ.
Person person0 = new Person("wansik", "choi");
Person person1 = new Person("wansik", "choi");
Person person2 = person0;
 
System.out.println(person0.equals(person1)); // false
System.out.println(person0.equals(person2)); // true

๊ฐ™๋‹ค๋Š” ์˜๋ฏธ๋Š” ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

  • iphone ๋‘๋Œ€๋Š” ๊ฐ™์€ ๊ฒƒ์ธ๊ฐ€? ์ผ๋ จ๋ฒˆํ˜ธ ๊ธฐ์ค€์œผ๋กœ ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฒƒ์ด ๋  ์ˆ˜๋„ ์žˆ์ง€ ์•Š์€๊ฐ€?
  • ์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค๋งˆ๋‹ค ๊ฐ™๋‹ค๋Š” ์˜๋ฏธ๋Š” ์ œ์ž‘์˜๋„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค.
  • ๋”ฐ๋ผ์„œ Class ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๊ตํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ํ•„์š”ํ•˜๋‹ค.
  • ์ด ๋•Œ, hashCode()๋„ ๋ฐ˜๋“œ์‹œ ๊ฐ™์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด์•ผ ํ•œ๋‹ค.

์˜ˆ์‹œ

public boolean equals(Object obj) {
    if (obj == this) { // ์•„์˜ˆ ์ฃผ์†Œ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ
        return true;
    }
 
    if (obj == null || !(obj instanceof Person)) { // null || Person์ด ์•„๋‹Œ ๊ฒฝ์šฐ - ์‚ฌ์‹ค ์—ฌ๊ธฐ์— hashCode๋„ ์žˆ์–ด์•ผ ํ•จ
        return false;
    }
 
    Person p = (Person) obj;
    return this.firstName.equals(p.firstName) && this.lastName.equals(p.lastName); // ๋‚ด์šฉ ๋น„๊ต
}
 
Person person0 = new Person("wansik", "choi");
Person person1 = new Person("wansik", "choi");
Person person2 = person0;
 
System.out.println(person0.equals(person1)); // true
System.out.println(person0.equals(person2)); // true
  • ์‚ฌ์‹ค hashCode ๋น„๊ต๊นŒ์ง€ ๊ฐ™์ด ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค.
  • ์•„๋ž˜ ์˜ˆ์‹œ๋กœ ์ ์–ด๋‘์—ˆ๋‹ค.

hashCode()

  • ์–ด๋–ค ๊ฐœ์ฒด๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ํ•ด์‹œ๊ฐ’์„ 32๋น„ํŠธ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜
    • ๋™์น˜์ธ ๋‘ ๊ฐœ์ฒด๋Š” ํ•ด์‹œ๊ฐ’์ด ๊ฐ™๋‹ค.
    • ๋™์น˜๊ฐ€ ์•„๋‹Œ ๋‘ ๊ฐœ์ฒด๋„ ํ•ด์‹œ๊ฐ’์ด ๊ฐ™์„ ์ˆ˜ ์žˆ๋‹ค. (ํ•ด์‹œ ์ถฉ๋Œ)
  • ๊ฐ™์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด, ํ•ด์‹œ๊ฐ’์€ ํ•ญ์ƒ ๊ฐ™์•„์•ผ ํ•œ๋‹ค.
    • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— equals()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ–ˆ๋‹ค๋ฉด ์ด๋…€์„๋„ ์ฑ™๊ฒจ์ฃผ์–ด์•ผ ์™„๋ฒฝํ•œ ๊ฒƒ.
    • ๋‹ค๋งŒ, ๋‘ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋„ ํ•ด์‹œ๊ฐ’์ด ๊ฐ™์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ธฐ๋ณธ ๊ตฌํ˜„: ๊ฐœ์ฒด์˜ ์ฃผ์†Œ๋ฅผ ๋ฐ˜ํ™˜

Object์— ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ์ด์œ 

  • ์ฃผ ๋ชฉ์ : HashMap์—์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ .
    • Key๋กœ ์‚ฌ์šฉ
  • ๋ถ€์ˆ˜ ํšจ๊ณผ
    • ๋น ๋ฅธ ๋น„๊ต์šฉ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (ํด๋ž˜์Šค๊ฐ€ ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•œ ๊ฒฝ์šฐ)
      • ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Œ
      • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— equals()์™€ pair๋กœ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•จ
    • ๋‹จ, ๋‘ ๊ฐœ์ฒด๊ฐ€ ๊ฐ™์ง€ ์•Š์Œ๋งŒ ๋น ๋ฅด๊ฒŒ ํŒ๋‹จ ๊ฐ€๋Šฅ

์˜ˆ์‹œ

public int hashCode() {
    return this.firstNAme.hashCode() ^ (this.lastName.hashCode() << 16); // XOR, Shift ์‚ฌ์šฉ
}
  • xor ์—ฐ์‚ฐ ์‚ฌ์šฉ
  • ๊ทผ๋ฐ ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด firstName๊ณผ lastName์˜ ๋‚ด์šฉ์ด ์ƒํ˜ธ๊ตํ™˜๋˜์–ด ๋“ค์–ด๊ฐ„ ๊ฒฝ์šฐ์™€ hash๊ฐ’์ด ๊ฐ™๊ฒŒ ๋‚˜์˜ด
  • shift๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ
  • ํ•˜๋‚˜์˜ ์˜ˆ์‹œ์ผ ๋ฟ ์˜ณ์€ ๊ฒƒ์€ ์•„๋‹˜
  • ์ข‹์€ hash ํ•จ์ˆ˜๋Š” ๊ตฌ๊ธ€์— ํ•œ๋ฒˆ ๊ฒ€์ƒ‰ํ•ด๋ณผ ๊ฒƒ
public boolean equals(Object obj) {
    if (obj == this) { // ์•„์˜ˆ ์ฃผ์†Œ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ
        return true;
    }
 
    if (obj == null || !(obj instanceof Person || this.hashCode() != obj.hashCode())) { // null || Person์ด ์•„๋‹Œ ๊ฒฝ์šฐ || HashCode๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ
        return false;
    }
 
    Person p = (Person) obj;
    return this.firstName.equals(p.firstName) && this.lastName.equals(p.lastName); // ๋‚ด์šฉ ๋น„๊ต
}
 
Person person0 = new Person("wansik", "choi");
Person person1 = new Person("wansik", "choi");
Person person2 = person0;
 
System.out.println(person0.equals(person1)); // true
System.out.println(person0.equals(person2)); // true
 
HashSet<Person> people = new HashSet<>();
 
people.add(person0)
 
System.out.println(people.contains(person0)); // true : ์ฃผ์†Œ๊ฐ€ ๊ฐ™์Œ
System.out.println(people.contains(person1)); // true : ๋‚ด์šฉ์ด ๊ฐ™์Œ
  • equals()์— hashCode()๊นŒ์ง€ ๋ฐ˜์˜๋œ ๋ฒ„์ „์ด๋‹ค.
  • ์ด ๊ฒฝ์šฐ HashMap์—์„œ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋ฌธ์ œ๊ฐ€ ์—†์ด ์˜๋„ํ•œ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค.

Reference