Skip to content

Latest commit

Β 

History

History
195 lines (157 loc) Β· 7.86 KB

item17.md

File metadata and controls

195 lines (157 loc) Β· 7.86 KB

item17) λ³€κ²½ κ°€λŠ₯성을 μ΅œμ†Œν™”ν•˜λΌ

λΆˆλ³€ 클래슀

  • 클래슀의 μΈμŠ€ν„΄μŠ€ 값을 μˆ˜μ •ν•  수 μ—†λŠ” 클래슀
  • String, Wrapper Class, BigInteger, BigDecimal

νŠΉμ§•

  • 섀계, κ΅¬ν˜„, μ‚¬μš©μ΄ 쉽닀.
  • 였λ₯˜μ—μ„œ κ°€λ³€ ν΄λž˜μŠ€λ³΄λ‹€ 훨씬 μ•ˆμ „ν•˜λ‹€.

κ΅¬ν˜„ 방법

  • 객체의 μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŒ. (예. setter)
  • 클래슀λ₯Ό ν™•μž₯ν•  수 없도둝 함.
    • ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ 객체가 변경될 수 μžˆλ‹€.
    • λŒ€ν‘œμ μΈ 방법은 final ν‚€μ›Œλ“œ
  • λͺ¨λ“  ν•„λ“œλ₯Ό final 둜 μ„ μ–Έ.
    • μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ 접근해도 값이 λ°”λ€Œμ§€ μ•ŠλŠ”λ‹€.
    • 닀쀑 μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œλ„ μ•ˆμ „ν•˜λ‹€.
  • λͺ¨λ“  ν•„λ“œλ₯Ό private 둜 μ„ μ–Έ.
  • μžμ‹  μ™Έμ—λŠ” λ‚΄λΆ€μ˜ κ°€λ³€ μ»΄ν¬λ„ŒνŠΈμ— μ ‘κ·Όν•  수 없도둝 함.
    • 클래슀의 κ°€λ³€ μ°Έμ‘° 객체 ν•„λ“œμ— λŒ€ν•œ ν•­λͺ©.
    • ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ 이 ν•„λ“œμ˜ μ°Έμ‘°λ₯Ό μ–»μœΌλ©΄ μ•ˆλœλ‹€.
    • μ„œλ²„μ—μ„œλ„ μ ‘κ·Όμž λ©”μ„œλ“œλ‘œ 이 ν•„λ“œκ°’μ„ λ°˜ν™˜ν•˜λ©΄ μ•ˆλœλ‹€.
    • μƒμ„±μž, μ ‘κ·Όμž, readObject λ©”μ„œλ“œ λͺ¨λ‘μ—μ„œ 방어적 볡사λ₯Ό μˆ˜ν–‰ν•œλ‹€.


λΆˆλ³€ 클래슀 Person

public final class Money {
    private final String currency;
    private final int amount;
    private final String[] cards;

    public Money(String currency, int amount) {
        this.currency = currency;
        this.amount = amount;
    }

    public Money plus(int additionMoney) {
        return new Money(this.name, this.amount + additionMoney);
    }

    public String[] getCards() {
        return cards.clone();
    }
}
  • 첫번째 ν•­λͺ©

    • 클래슀의 ν•„λ“œ currency, amount λ₯Ό λ°”κΏ€ 수 μžˆλŠ” λ©”μ„œλ“œκ°€ μ—†μŒ.
    • λ‚˜μ΄λ₯Ό λŠ˜λ¦¬λŠ” λ©”μ„œλ“œλŠ” μƒˆλ‘œμš΄ Money 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
    ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° :  자료 처리λ₯Ό μˆ˜ν•™μ  ν•¨μˆ˜μ˜ κ³„μ‚°μœΌλ‘œ μ·¨κΈ‰ν•˜κ³  μƒνƒœμ™€ κ°€λ³€ 데이터λ₯Ό λ©€λ¦¬ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ˜ ν•˜λ‚˜
    
    순수 ν•¨μˆ˜ : λΆ€μž‘μš©μ΄ μ—†λŠ” ν•¨μˆ˜
    λΆ€μž‘μš©(side-effect) : ν•¨μˆ˜μ˜ 싀행이 외뢀에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•Šκ³ , 외뢀에 μ˜ν•΄ ν•¨μˆ˜μ˜ 싀행이 영ν–₯받지 μ•ŠλŠ” ν•¨μˆ˜.
    
    λ‚˜μ΄λ₯Ό 늘릴 λ•Œ, ν•΄λ‹Ή 객체의 κ°’(속성)을 λ³€κ²½ν•œλ‹€λ©΄ κ·Έ 객체λ₯Ό μ‚¬μš©ν•˜λŠ” λ‹€λ₯Έ 객체듀이 영ν–₯을 λ°›λŠ”λ‹€.
    λ”°λΌμ„œ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ–΄ λ°˜ν™˜ν•¨μœΌλ‘œμ¨ side-effect λ₯Ό 쀄일 수 μžˆλ‹€.
    
    μƒˆλ‘œμš΄ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œλŠ” λͺ…λͺ… κ·œμΉ™μœΌλ‘œ μ „μΉ˜μ‚¬λ₯Ό μ‚¬μš©.
    (add 말고 plus)
    
    Integer, Double 같은 ν΄λž˜μŠ€λ“€μ˜ valueOf() 
    
  • λ‘λ²ˆμ§Έ ν•­λͺ©

    • 클래슀λ₯Ό final 둜 μ§€μ •ν•˜μ—¬ ν™•μž₯이 λΆˆκ°€λŠ₯ν•˜κ²Œ 함.
  • μ„Έλ²ˆμ§Έ ν•­λͺ©

    • λͺ¨λ“  ν•„λ“œλ₯Ό final 둜 μ„ μ–Έ.
  • λ„€λ²ˆμ§Έ ν•­λͺ©

    • λͺ¨λ“  ν•„λ“œλ₯Ό private 으둜 μ„ μ–Έ.
  • λ‹€μ„―λ²ˆμ§Έ ν•­λͺ©

    • κ°€λ³€ μ°Έμ‘° 객체 cards λŠ” final 둜 μ§€μ •ν•˜λ”λΌλ„ μ•ˆμ˜ 값에 λŒ€ν•΄μ„œλŠ” λΆˆλ³€μ΄ μ•„λ‹˜.
    • κ°€λ³€ 객체 cards λ₯Ό μ–»μ–΄μ˜€λŠ” ν•„λ“œλŠ” clone() 을 이용.

λΆˆλ³€ 객체의 μž₯점

  1. λ‹¨μˆœν•˜λ‹€.

    1. μƒμ„±λœ μ‹œμ μ˜ μƒνƒœκ°€ 파괴될 λ•ŒκΉŒμ§€ 간직
  2. λΆˆλ³€ κ°μ²΄λŠ” 근본적으둜 μŠ€λ ˆλ“œ μ•ˆμ „ν•˜μ—¬ λ”°λ‘œ 동기화 ν•  ν•„μš” μ—†λ‹€.

    1. Thread-safe ν•œ 클래슀λ₯Ό λ§Œλ“œλŠ” κ°€μž₯ μ‰¬μš΄ 방법.
    2. λΆˆλ³€ ν΄λž˜μŠ€λŠ” ν•œλ²ˆ λ§Œλ“  μΈμŠ€ν„΄μŠ€λ₯Ό μ΅œλŒ€ν•œ ν™œμš©ν•œλ‹€. (예. public static final 상)
    3. λ”°λΌμ„œ λΆˆλ³€ κ°μ²΄λŠ” μ•ˆμ‹¬ν•˜κ³  κ³΅μœ ν•  수 μžˆλ‹€.
    java.math.BigDecimal
    
    public static BigDecimal valueOf(long val) {
        if (val >= 0 && val < ZERO_THROUGH_TEN.length)
            return ZERO_THROUGH_TEN[(int)val];
        else if (val != INFLATED)
            return new BigDecimal(null, val, 0, 0);
        return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
    }
    
    
    private static final BigDecimal ZERO_THROUGH_TEN[] = {
        new BigDecimal(BigInteger.ZERO,       0,  0, 1),
        new BigDecimal(BigInteger.ONE,        1,  0, 1),
        new BigDecimal(BigInteger.TWO,        2,  0, 1),
        new BigDecimal(BigInteger.valueOf(3), 3,  0, 1),
        new BigDecimal(BigInteger.valueOf(4), 4,  0, 1),
        new BigDecimal(BigInteger.valueOf(5), 5,  0, 1),
        new BigDecimal(BigInteger.valueOf(6), 6,  0, 1),
        new BigDecimal(BigInteger.valueOf(7), 7,  0, 1),
        new BigDecimal(BigInteger.valueOf(8), 8,  0, 1),
        new BigDecimal(BigInteger.valueOf(9), 9,  0, 1),
        new BigDecimal(BigInteger.TEN,        10, 0, 2),
    };
    @Before
    public void μ„€μ •() {
        tenUnder1 = BigDecimal.valueOf(9);
        tenUnder2 = BigDecimal.valueOf(9);
        tenOver1 = BigDecimal.valueOf(12);
        tenOver2 = BigDecimal.valueOf(12);
    
    @Test
    public void BigDecimalμ—μ„œ_10μ΄ν•˜λŠ”_μ •μ νŒ©ν„°λ¦¬μ‚¬μš©() {
        Assert.assertSame(tenUnder1, tenUnder2);
        Assert.assertEquals(System.identityHashCode(tenUnder1), System.identityHashCode(tenUnder2));
    
    @Test
    public void BigDecimalμ—μ„œ_10μ΄ˆκ³ΌλŠ”_μƒˆλ‘œμš΄κ°μ²΄μƒμ„±() {
        Assert.assertNotSame(tenOver1, tenOver2);
        Assert.assertNotEquals(System.identityHashCode(tenOver1), System.identityHashCode(tenOver2));
    }
  3. λΆˆλ³€ κ°μ²΄λŠ” 객체의 ν•„λ“œλ‘œ μ“°λ©΄ μ’‹λ‹€.

    1. λΆˆλ³€μ‹μ„ 보μž₯ν•  수 μžˆλ‹€.
    2. Map 의 ν‚€λ‚˜ Set 의 μš”μ†Œλ‘œ λΆˆλ³€κ°μ²΄λ₯Ό μ‚¬μš©ν•˜λ©΄ λΆˆλ³€μ‹μ„ 지킀기 쉽닀.
  4. λΆˆλ³€ κ°μ²΄λŠ” μ‹€νŒ¨ μ›μžμ„±μ„ μ œκ³΅ν•œλ‹€.

    1. μ‹€νŒ¨ μ›μžμ„± : λ©”μ„œλ“œ μˆ˜ν–‰ 쀑 μ˜ˆμ™Έκ°€ λ°œμƒν•΄λ„ κ°μ²΄λŠ” μƒνƒœλ₯Ό μœ μ§€ν•œλ‹€. (item76)

λΆˆλ³€ 객체의 단점

  1. 값이 λ‹€λ₯΄λ©΄ 무쑰건 λ…λ¦½λœ 객체λ₯Ό 생성해야 함.
    1. μ›ν•˜λŠ” 객체λ₯Ό λ§Œλ“€κΈ° κΉŒμ§€ μ—¬λŸ¬ 단계λ₯Ό 거쳐야 ν•œλ‹€λ©΄, μ“Έλͺ¨μ—†λŠ” 객체가 많이 생긴닀.
    2. μœ„ 문제의 ν•΄κ²°μ μœΌλ‘œ 닀단계 연산을 μ œν•˜λŠ” κ°€λ³€ λ™λ°˜ 클래슀 λ₯Ό μž‘μ„±ν•œλ‹€.
    κ°€λ³€ λ™λ°˜ 클래슀 : λ³΅μž‘ν•œ 닀단계 연산을 기본으둜 제곡 ν•΄μ£ΌλŠ” 클래슀
    
    BigInteger μ—λŠ” package-private 으둜 μ—¬λŸ¬ 클래슀 쑴재
    String μ—λŠ” public 으둜 μ œκ³΅λ˜λŠ” StringBuilder, StringBuffer 쑴재
    κ°€λ³€λ™λ°˜

λΆˆλ³€ 클래슀λ₯Ό λ§Œλ“œλŠ” λ‹€λ₯Έ 방법

  • λ‘λ²ˆμ§Έ κ·œμΉ™. ν™•μž₯ν•  수 없도둝 함

    • λͺ¨λ“  μƒμ„±μžλ₯Ό private, package-private 으둜 λ§Œλ“€κ³ , 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ 제곡.
  • 첫, μ„Έλ²ˆμ§Έ κ·œμΉ™. λͺ¨λ“  ν•„λ“œλŠ” final 이고 λ³€κ²½μž λ©”μ„œλ“œκ°€ μ—†μŒ

    • μ–΄λ–€ λΆˆλ³€ ν΄λž˜μŠ€λŠ” 계산 λΉ„μš©μ΄ 큰 값을 final 이 μ•„λ‹Œ ν•„λ“œμ— μΊμ‹±ν•˜μ—¬ μ‚¬μš©ν•œλ‹€.
    public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
        @Stable
        private final byte[] value;
        private final byte coder;
        private int hash; // final 이 μ•„λ‹Œ ν•„
        private static final long serialVersionUID = -6849794470754667710L;
    
        ...
    
        public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                hash = h = isLatin1() ? StringLatin1.hashCode(value)
                                      : StringUTF16.hashCode(value);
            }
            return h;
        }
    • λ”°λΌμ„œ μœ„μ˜ κ·œμΉ™μ„ λ‹€μŒκ³Ό 같이 μ™„ν™”ν•  수 μžˆλ‹€.

      μ–΄λ–€ λ©”μ„œλ“œλ„ 객체의 μƒνƒœ 쀑 외뢀에 λΉ„μΉ˜λŠ” 값을 λ³€κ²½ν•  수 μ—†λ‹€.

κ²°λ‘ 

  • λŒ€λΆ€λΆ„μ˜ 경우 λΆˆλ³€ 클래슀둜 λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. : setter 쓰지 말 것.
  • μ„±λŠ₯ μ €ν•˜λ‘œ λΆˆλ³€ 클래슀 κ΅¬ν˜„μ΄ νž˜λ“€λ©΄ κ°€λ³€ λ™λ°˜ 클래슀λ₯Ό 이용.
  • λΆˆλ³€ 클래슀 κ΅¬ν˜„μ΄ λΆˆκ°€ν•˜λ©΄ λ³€κ²½ κ°€λŠ₯ 뢀뢄을 μ΅œμ†Œν•œμœΌλ‘œ μ€„μž„.
    • λͺ¨λ“  ν•„λ“œλŠ” private final 이어야 ν•œλ‹€.
  • 객체의 μƒνƒœλ₯Ό μ΄ˆκΈ°ν™” ν•˜λŠ” λ©”μ„œλ“œλŠ” μƒμ„±μž, 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ μ΄μ™Έμ—λŠ” μ—†μ–΄μ•Ό 함.