item 2 Jung inchul - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e μ•„μ΄ν…œ 2λ₯Ό μš”μ•½ν•œ λ‚΄μš© μž…λ‹ˆλ‹€.

정적 νŒ©ν„°λ¦¬μ™€ μƒμ„±μžμ—λŠ” λ˜‘κ°™μ€ μ œμ•½μ΄ ν•˜λ‚˜ μžˆλ‹€. 선택적 λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ„ λ•Œ 적절히 λŒ€μ‘ν•˜κΈ° μ–΄λ ΅λ‹€λŠ” 점이닀.

ν”„λ‘œκ·Έλž˜λ¨Έλ“€μ€ 이럴 λ•Œ 점측적 μƒμ„±μž νŒ¨ν„΄μ„ 즐겨 μ‚¬μš©ν–ˆλ‹€.

점측적 μƒμ„±μž νŒ¨ν„΄μ΄λž€?
ν•„μˆ˜ λ§€κ°œλ³€μˆ˜λ§Œ λ°›λŠ” μƒμ„±μž , ν•„μˆ˜ λ§€κ°œλ³€μˆ˜μ™€ 선택 λ§€κ°œλ³€μˆ˜ 1개λ₯Ό λ°›λŠ” μƒμ„±μž ν˜•νƒœλ‘œ 선택 λ§€κ°œλ³€μˆ˜λ₯Ό μ „λΆ€ λ‹€ λ°›λŠ” μƒμ„±μžκΉŒμ§€ λŠ˜λ €κ°€λŠ” 방식

public class Student {
    private String name;
    private String email;
    private String class;
    private int age;

    // μ΅œμ†Œ μš”κ΅¬μ‘°κ±΄
    public Student(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public Student(String name, String email, String address, String class) {
        this.name = name;
        this.email = email;
        this.class = class;
    }

    public Student(String name, String email, String class, int age) {
        this.name = name;
        this.email = email;
        this.class = class;
        this.age = age;
    }
}

점측적 μƒμ„±μž νŒ¨ν„΄λ„ μ“Έ μˆ˜λŠ” μžˆμ§€λ§Œ, λ§€κ°œλ³€μˆ˜ κ°œμˆ˜κ°€ λ§Žμ•„μ§€λ©΄ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ±°λ‚˜ 읽기 μ–΄λ ΅λ‹€.

ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‹€μˆ˜λ‘œ λ§€κ°œλ³€μˆ˜μ˜ μˆœμ„œλ₯Ό λ°”κΏ” κ±΄λ„€μ€˜λ„ μ»΄νŒŒμΌλŸ¬λŠ” μ•Œμ•„μ±„μ§€ λͺ»ν•˜κ³ , κ²°κ΅­ λŸ°νƒ€μž„μ— μ—‰λš±ν•œ λ™μž‘μ„ ν•˜κ²Œ λœλ‹€.

μ΄λ²ˆμ—λŠ” 선택 λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ„ λ•Œ ν™œμš©ν•  수 μžˆλŠ” 두 번째 λŒ€μ•ˆμΈ μžλ°”λΉˆμ¦ˆνŒ¨ν„΄μ„ 보겠닀. λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” μƒμ„±μžλ‘œ 객체λ₯Ό λ§Œλ“  ν›„, Setter λ©”μ„œλ“œλ“€μ„ ν˜ΈμΆœν•΄ μ›ν•˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ 값을 μ„€μ •ν•˜λŠ” 방식이닀.

public class NutritionFacts {
	private int servingSize = -1;
	private int servings = -1;
	private int calories = 0;
	private int fat = 0;
	private int sodium = 0;
	private int carbohydrate = 0;

	public NutritionFacts() { }

	public void setServingSize(int val) { ... }
	public void setServings(int servings) { ... }
	public void setCalories(int calories) { ... }
	public void setFat(int fat) { ... }
	public void setSodium(int sodium) { ... }
	public void setCarbohydrate(int carbohydrate) { ... }

}

μ½”λ“œκ°€ 길어지긴 ν–ˆμ§€λ§Œ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€κΈ° 쉽고, κ·Έ κ²°κ³Ό 더 읽기 μ‰¬μš΄ μ½”λ“œκ°€ λ˜μ—ˆλ‹€.

μžλ°”λΉˆμ¦ˆνŒ¨ν„΄μ—μ„œλŠ” 객체 ν•˜λ‚˜λ₯Ό λ§Œλ“€λ €λ©΄ λ©”μ„œλ“œλ₯Ό μ—¬λŸ¬ 개 ν˜ΈμΆœν•΄μ•Ό ν•˜κ³ , 객체가 μ™„μ „νžˆ μƒμ„±λ˜κΈ° μ „κΉŒμ§€λŠ” **일관성(consistency)**이 λ¬΄λ„ˆμ§„ μƒνƒœμ— λ†“μ΄κ²Œ λœλ‹€.

이처럼 일관성이 λ¬΄λ„ˆμ§€λŠ” 문제 λ•Œλ¬Έμ— μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄μ—μ„œλŠ” 클래슀λ₯Ό λΆˆλ³€μœΌλ‘œ λ§Œλ“€ 수 μ—†μœΌλ©° μŠ€λ ˆλ“œ μ•ˆμ „μ„±μ„ μ–»μœΌλ €λ©΄ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μΆ”κ°€ μž‘μ—…μ„ ν•΄μ€˜μ•Όλ§Œ ν•œλ‹€.

Q1. μŠ€λ ˆλ“œ μ•ˆμ •μ„±μ΄ ν•„μš”ν•  경우 ν•„μš”ν•œ μΆ”κ°€ μž‘μ—…μ΄λž€?

μ΄λŸ¬ν•œ 단점을 μ™„ν™”ν•˜κ³ μž 생성이 λλ‚œ 객체λ₯Ό μˆ˜λ™μœΌλ‘œ '얼리고(freezing)' 얼리기 μ „μ—λŠ” μ‚¬μš©ν•  수 없도둝 ν•˜κΈ°λ„ ν•œλ‹€.

Q2. μžλ°”μ—λ„ 얼릴 수 μžˆλŠ” 방법이 μžˆλ‚˜?

λ‹€ν–‰νžˆ μš°λ¦¬μ—κ² μ„Έ 번째 λŒ€μ•ˆμ΄ μžˆλ‹€.

점측적 μƒμ„±μž νŒ¨ν„΄μ˜ μ•ˆμ „μ„±κ³Ό μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄μ˜ 가독성을 κ²ΈλΉ„ν•œ λΉŒλ” νŒ¨ν„΄μ΄λ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” ν•„μš”ν•œ 객체λ₯Ό 직접 λ§Œλ“œλŠ” λŒ€μ‹ , ν•„μˆ˜ λ§€κ°œλ³€μˆ˜λ§ŒμœΌλ‘œ μƒμ„±μž(ν˜Ήμ€ 정적 νŒ©ν„°λ¦¬)λ₯Ό ν˜ΈμΆœν•΄ λΉŒλ” 객체λ₯Ό μ–»λŠ”λ‹€.

λΉŒλ”λŠ” 생성할 클래슀 μ•ˆμ— 정적 멀버 클래슀둜 λ§Œλ“€μ–΄λ‘λŠ”κ²Œ 보톡이닀.

    public class NutritionFacts {
    	private final int servingSize;
    	private final int servings;
    	private final int calories;
    	private final int fat;
    	private final int sodium;
    	private final int carbohydrate;
    
    	public static class Builder {
    		// ν•„μˆ˜ λ§€κ°œλ³€μˆ˜
    		private final int servingSize;
    		private final int servings;
    
    		// 선택 λ§€κ°œλ³€μˆ˜ - κΈ°λ³Έκ°’μœΌλ‘œ μ΄ˆκΈ°ν™”ν•œλ‹€. 
    		private int calories = 0;
    		private int fat = 0;
    		private int sodium = 0;
    		private int carbohydrate = 0;
    
    		public Builder(int servingSize, int servings) {
    			this.servingSize = servingSize;
    			this.servings = servings;
    		}
    
    		public Builder calories(int val) { calories = val; return this }
    		public Builder fat(int val) { fat = val; return this }
    		public Builder sodium(int val) { sodium = val; return this }
    		public Builder carbohydrate(int val) { carbohydrate = val; return this }
    
    		private NutritionFacts(Builder builder) {
    			servingSize = builder.servingSize;
    			servings = builder.servings;
    			calories = builder.calories;
    			fat = builder.fat;
    			sodium = builder.sodium;
    			carbohydrate = builder.carbohydrate;
    		}
    }

λΉŒλ”μ˜ μ„Έν„° λ©”μ„œλ“œλ“€μ€ λΉŒλ” μžμ‹ μ„ λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— μ—°μ‡„μ μœΌλ‘œ ν˜ΈμΆœν•  수 μžˆλ‹€.

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).fat(35).sodium(40).carbohydrate(1).build();

이 ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλŠ” μ“°κΈ° 쉽고, 무엇보닀도 읽기 쉽닀.

λΉŒλ” νŒ¨ν„΄μ€ μƒλ‹Ήνžˆ μœ μ—°ν•˜λ‹€. λΉŒλ” ν•˜λ‚˜λ‘œ μ—¬λŸ¬ 객체λ₯Ό μˆœνšŒν•˜λ©΄μ„œ λ§Œλ“€ 수 있고, λΉŒλ”μ— λ„˜κΈ°λŠ” λ§€κ°œλ³€μˆ˜μ— 따라 λ‹€λ₯Έ 객체λ₯Ό λ§Œλ“€ μˆ˜λ„ μžˆλ‹€.

λΉŒλ” νŒ¨ν„΄μ— μž₯점만 μžˆλŠ” 것은 μ•„λ‹ˆλ‹€. 객체λ₯Ό λ§Œλ“€λ €λ©΄ 그에 μ•žμ„œ λΉŒλ”λΆ€ν„° λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. λΉŒλ” 생성 λΉ„μš©μ΄ ν¬μ§€λŠ” μ•Šμ§€λ§Œ μ„±λŠ₯에 λ―Όκ°ν•œ μƒν™©μ—μ„œλŠ” λ¬Έμ œκ°€ 될 수 μžˆλ‹€.

μƒμ„±μžλ‚˜ 정적 νŒ©ν„°λ¦¬ λ°©μ‹μœΌλ‘œ μ‹œμž‘ν–ˆλ‹€κ°€ λ‚˜μ€‘μ— λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ•„μ§€λ©΄ λΉŒλ” νŒ¨ν„΄μœΌλ‘œ μ „ν™˜ν•  μˆ˜λ„ μžˆμ§€λ§Œ, 이전에 λ§Œλ“€μ–΄λ‘” μƒμ„±μžμ™€ 정적 νŒ©ν„°λ¦¬κ°€ μ•„μ£Ό λ„λ“œλΌμ Έ 보일 것이닀. κ·ΈλŸ¬λ‹ˆ μ• μ΄ˆμ— λΉŒλ”λ‘œ μ‹œμž‘ν•˜λŠ” 편이 λ‚˜μ„ λ•Œκ°€ λ§Žλ‹€.

Q3. μŠ€ν”„λ§μ—μ„œλŠ” lombok을 μ‚¬μš©ν•˜μ—¬ Builder μ–΄λ…Έν…Œμ΄μ…˜λ§ŒμœΌλ‘œ λΉŒλ” νŒ¨ν„΄μ„ κ΅¬ν˜„ν•  수 μžˆλ‹€. 그런데 ν•„μˆ˜ κ°’ 섀정이 κ°€λŠ₯ν• κΉŒ?

@Builder
public class  User {
    @Builder.Default private String name = "incheol";
    private String address;
    private Integer age;

    public static void main(String[] args) {
        User incheol = User.builder()
                                .address("seongnamsi")
                                .age(10)
                                .build();
    }
}

정리

μƒμ„±μžλ‚˜ 정적 νŒ©ν„°λ¦¬κ°€ μ²˜λ¦¬ν•΄μ•Ό ν•  λ§€κ°œλ³€μˆ˜κ°€ λ§Žλ‹€λ©΄ λΉŒλ” νŒ¨ν„΄μ„ μ„ νƒν•˜λŠ” 게 더 λ‚«λ‹€. λ§€κ°œλ³€μˆ˜ 쀑 λ‹€μˆ˜κ°€ ν•„μˆ˜κ°€ μ•„λ‹ˆκ±°λ‚˜ 같은 νƒ€μž…μ΄λ©΄ 특히 더 κ·Έλ ‡λ‹€. λΉŒλ”λŠ” 점측적 μƒμ„±μžλ³΄λ‹€ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό 읽고 μ“°κΈ°κ°€ 훨씬 κ°„κ²°ν•˜κ³  μžλ°”λΉˆμ¦ˆλ³΄λ‹€ 훨씬 μ•ˆμ „ν•˜λ‹€.

⚠️ **GitHub.com Fallback** ⚠️