Java/πŸ“• Effective Java

[Effective Java] ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ δΈ‹

soogoori 2024. 10. 6. 20:52

23. νƒœκ·Έ 달린 ν΄λž˜μŠ€λ³΄λ‹€λŠ” 클래슀 계측 ꡬ쑰 ν™œμš©ν•˜κΈ°

νƒœκ·Έ 달린 클래슀 πŸ‘‰ μƒμˆ˜ ν•„λ“œλ‚˜ μΈν„°νŽ˜μ΄μŠ€, μ—΄κ±°ν˜•(enum) 등을 ν™œμš©ν•΄μ„œ νŠΉμ • 객체가 μ–΄λ–€ μΉ΄ν…Œκ³ λ¦¬μ— μ†ν•˜λŠ”μ§€ 식별
class Figure {
    enum Shape {RECTANGLE, CIRCLE};

    // νƒœκ·Έ ν•„λ“œ - ν˜„μž¬ λͺ¨μ–‘을 λ‚˜νƒ€λ‚Έλ‹€.
    final Shape shape;

    // λ‹€μŒ ν•„λ“œλ“€μ€ λͺ¨μ–‘이 μ‚¬κ°ν˜•(RECTANGLE)일 λ•Œλ§Œ 쓰인닀.
    double length;
    double width;

    // λ‹€μŒ ν•„λ“œλŠ” λͺ¨μ–‘이 원(CIRCLE)일 λ•Œλ§Œ 쓰인닀.
    double radius;

    // μ›μš© μƒμ„±μž
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }

    // μ‚¬κ°ν˜•μš© μƒμ„±μž
    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }

    double area() {
        switch (shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * (radius * radius);
            default:
                throw new AssertionError(shape);
        }
    }
}
  • μ—΄κ±°νƒ€μž… μ„ μ–Έ, νƒœκ·Έ ν•„λ“œ, switch λ¬Έ λ“± 쓸데 μ—†λŠ” μ½”λ“œκ°€ 많음
  • μ—¬λŸ¬ κ΅¬ν˜„μ΄ ν•œ 클래슀 μ•ˆμ— ν˜Όν•©λΌ μžˆμ–΄μ„œ 가독성이 λ‚˜μ¨
  • λ‹€λ₯Έ 의미λ₯Ό μœ„ν•œ μ½”λ“œλ„ μ–Έμ œλ‚˜ ν•¨κ»˜ ν•΄ λ©”λͺ¨λ¦¬λ₯Ό 많이 μ‚¬μš©
  • μƒˆλ‘œμš΄ 의미λ₯Ό μΆ”κ°€ν•  λ•Œλ§ˆλ‹€ λͺ¨λ“  switch문을 μ°Ύμ•„ μƒˆ 의미λ₯Ό μ²˜λ¦¬ν•˜λŠ” μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ•Ό 함
  • μΈμŠ€ν„΄μŠ€μ˜ νƒ€μž…λ§ŒμœΌλ‘œλŠ” ν˜„μž¬ λ‚˜νƒ€λ‚΄λŠ” 의미λ₯Ό μ•Œ 수 μ—†μŒ 

πŸ‘‰ νƒœκ·Έ 달린 ν΄λž˜μŠ€λŠ” μž₯ν™©ν•˜κ³  였λ₯˜λ₯Ό λ‚΄κΈ° 쉽고, λΉ„νš¨μœ¨μ μž„


✳️ νƒœκ·Έ 달린 클래슀λ₯Ό 클래슀 계측 ꡬ쑰둜 λ°”κΎΈκΈ°  

  • 계측 ꡬ쑰의 λ£¨νŠΈκ°€ 될 좔상 클래슀 μ •μ˜ν•˜κ³  νƒœκ·Έ 값에 따라 λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” λ©”μ„œλ“œλ“€μ„ 루트 클래슀의 좔상 λ©”μ„œλ“œλ‘œ μ„ μ–Έ
    πŸ‘‰ μœ„μ˜ μ½”λ“œμ—μ„œ area에 ν•΄λ‹Ή
  • νƒœκ·Έ 값에 상관없이 λ™μž‘μ΄ μΌμ •ν•œ λ©”μ„œλ“œλ“€μ„ 루트 ν΄λž˜μŠ€μ— 일반 λ©”μ„œλ“œλ‘œ μΆ”κ°€ 
  • λͺ¨λ“  ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ³΅ν†΅μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 데이터 ν•„λ“œλ“€μ„ μ „λΆ€ 루트 클래슀둜 올림
  • 루트 클래슀λ₯Ό ν™•μž₯ν•œ ꡬ체 클래슀λ₯Ό μ˜λ―Έλ³„λ‘œ ν•˜λ‚˜μ”© μ •μ˜
abstract class Figure{
	abstract double area();
}

class Circle extends Figure{
	final double radius;
    
    Circle(double radius) { this.radius = radius; }
    
    @Override 
    double area() {
    	return Math.PI * (radius * radius);
    }
}	

class Rectangle extends Figure{
	final double length;
    final double width;
    
    Rectangle(double length, double width) {
    	this.length = length;
        this.width = width;   
    }
    
    @Override 
    double area() {
    	return length * width;
    }
}

 

 

 

24. 멀버 ν΄λž˜μŠ€λŠ” λ˜λ„λ‘μ΄λ©΄ static으둜 λ§Œλ“€κΈ° 

쀑첩 ν΄λž˜μŠ€λž€ λ‹€λ₯Έ 클래슀 μ•ˆμ— μ •μ˜λœ 클래슀
πŸ‘‰ μ’…λ₯˜ : 정적 멀버 클래슀, (비정적) 멀버 클래슀, 읡λͺ… 클래슀, 지역 클래슀

 

✳️ 정적 멀버 클래슀  

  • λ‹€λ₯Έ 클래슀 μ•ˆμ— 선언됨
  • λ°”κΉ₯ ν΄λž˜μŠ€μ™€ ν•¨κ»˜ 쓰일 λ•Œλ§Œ μœ μš©ν•œ public λ„μš°λ―Έ 클래슀둜 μ“°μž„
  • μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€μ™€ 관계없이 λ…λ¦½μ μœΌλ‘œ μ‚¬μš©
class OuterClass {
    private static String staticField = "Outer Static Field";
    private String instanceField = "Outer Instance Field";

    // 정적 멀버 클래슀 μ„ μ–Έ
    static class HelperClass {
        public void display() {
            // 정적 멀버 ν΄λž˜μŠ€λŠ” μ™ΈλΆ€ 클래슀의 정적 ν•„λ“œμ— μ ‘κ·Ό κ°€λŠ₯
            System.out.println("Accessing outer static field: " + staticField);
            
            // μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€ ν•„λ“œλŠ” μ ‘κ·Ό λΆˆκ°€ (컴파일 μ—λŸ¬ λ°œμƒ)
            // System.out.println("Accessing outer instance field: " + instanceField);
        }
        
        // 헬퍼 μ—­ν• : νŠΉμ • μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œ 제곡
        public static int add(int a, int b) {
            return a + b;
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 정적 멀버 ν΄λž˜μŠ€λŠ” μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€ 없이 생성 κ°€λŠ₯
        OuterClass.HelperClass helper = new OuterClass.HelperClass();
        helper.display();
        
        // 정적 헬퍼 λ©”μ„œλ“œ 호좜
        int result = OuterClass.HelperClass.add(5, 3);
        System.out.println("Result of addition: " + result);
    }
}

 

 

✳️ (비정적) 멀버 클래슀 

  • μΈμŠ€ν„΄μŠ€κ°€ λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€μ™€ μ•”λ¬΅μ μœΌλ‘œ 연결됨 πŸ‘‰ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€ μ—†μ΄λŠ” 생성 λΆˆκ°€ 
  • μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ—μ„œ μ •κ·œν™”λœ this (= 클래슀λͺ….this)λ₯Ό μ‚¬μš©ν•΄ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€μ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€μ˜ μ°Έμ‘°λ₯Ό κ°€μ Έμ˜¬ 수 있음
  • μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 감싸 λ‹€λ₯Έ 클래슀의 μΈμŠ€ν„΄μŠ€μ²˜λŸΌ 보이게 ν•˜λŠ” 뷰둜 μ‚¬μš©
class OuterClass {
    private String message = "Hello from OuterClass";

    // 비정적 멀버 클래슀
    class InnerClass {
        void display() {
            // λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€ ν•„λ“œμ— μ ‘κ·Ό
            System.out.println("Accessing: " + message);

            // λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ 호좜
            OuterClass.this.outerMethod();
        }
    }

    void outerMethod() {
        System.out.println("Outer method called");
    }
}

public class Main {
    public static void main(String[] args) {
        // OuterClass μΈμŠ€ν„΄μŠ€ 생성
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();  // InnerClass μΈμŠ€ν„΄μŠ€ 생성
        inner.display();  // display λ©”μ„œλ“œ 호좜
    }
}
  • 비정적 멀버 ν΄λž˜μŠ€λŠ” μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€μ™€ μ—°κ²°λ˜μ–΄ μžˆμ–΄, μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€ ν•„λ“œμ™€ λ©”μ„œλ“œμ— μ ‘κ·Όν•  수 있음
  • 이 경우, 비정적 멀버 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ 생성될 λ•Œλ§ˆλ‹€ μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€μ— λŒ€ν•œ μˆ¨μ€ μ°Έμ‘°κ°€ μžλ™μœΌλ‘œ 생성됨
멀버 ν΄λž˜μŠ€μ—μ„œ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€μ— μ ‘κ·Όν•  일이 μ—†λ‹€λ©΄ 무쑰건 static λΆ™μ—¬μ„œ 정적 멀버 클래슀둜 λ§Œλ“€κΈ° ! 
πŸ‘‰ static μƒλž΅ μ‹œ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€λ‘œμ˜ μˆ¨μ€ μ™ΈλΆ€ μ°Έμ‘°λ₯Ό κ°–κ²Œ λ˜λ―€λ‘œ μ‹œκ°„κ³Ό 곡간이 μ†ŒλΉ„λ˜κ±°λ‚˜ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ°œμƒ κ°€λŠ₯ 

 

✳️ 읡λͺ… 클래슀 

  • 이름이 μ—†μŒ
  • λ°”κΉ₯ 클래슀의 멀버가 μ•„λ‹˜
  • μ“°μ΄λŠ” μ‹œμ μ— μ„ μ–Έκ³Ό λ™μ‹œμ— μΈμŠ€ν„΄μŠ€κ°€ λ§Œλ“€μ–΄μ§ 
  • 비정적인 λ¬Έλ§₯μ—μ„œ μ‚¬μš©λ  λ•Œλ§Œ λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€ μ°Έμ‘° κ°€λŠ₯
  • μ„ μ–Έν•œ μ§€μ μ—μ„œλ§Œ μΈμŠ€ν„΄μŠ€ 생성 κ°€λŠ₯
  • instanceof κ²€μ‚¬λ‚˜ 클래슀의 이름이 ν•„μš”ν•œ μž‘μ—…μ€ μˆ˜ν–‰ λΆˆκ°€
  • μ—¬λŸ¬ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ λΆˆκ°€
  • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” λ™μ‹œμ— λ‹€λ₯Έ 클래슀 상속 λΆˆκ°€ 
  • 읡λͺ… 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” κ·Έ 읡λͺ… ν΄λž˜μŠ€κ°€ μƒμœ„ νƒ€μž…μ—μ„œ μƒμ†ν•œ 멀버 μ™Έμ—λŠ” 호좜 λΆˆκ°€ 
  • 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•  λ•Œ 주둜 μ‚¬μš©λ¨ 
class OuterClass {
    void display() {
        // 읡λͺ… λ‚΄λΆ€ 클래슀
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("This is an anonymous inner class.");
            }
        };

        // μ‹€ν–‰
        runnable.run();
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.display();
    }
}

✳️ 지역 클래슀 

  • κ°€μž₯ λ“œλ¬Όκ²Œ μ‚¬μš©
  • 지역 λ³€μˆ˜λ₯Ό μ„ μ–Έν•  수 μžˆλŠ” 곳이면 μ‹€μ§ˆμ μœΌλ‘œ μ–΄λ””μ„œλ“  μ„ μ–Έ κ°€λŠ₯
  • 이름이 있고 λ°˜λ³΅ν•΄μ„œ μ‚¬μš© κ°€λŠ₯
  • 비정적 λ¬Έλ§₯μ—μ„œ μ‚¬μš©λ  λ•Œλ§Œ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•  수 있음
  • 정적 멀버λ₯Ό κ°€μ§ˆ 수 μ—†μœΌλ©° 가독성을 μœ„ν•΄ 짧게 μž‘μ„±ν•΄μ•Ό 함
class OuterClass {

	private String outerField = "Outer Field";
    
    void display() {
        class LocalInnerClass {
            void print() {
            
            	// 비정적 λ¬Έλ§₯μ—μ„œλŠ” μ™ΈλΆ€ 클래슀의 μΈμŠ€ν„΄μŠ€ ν•„λ“œ μ ‘κ·Ό κ°€λŠ₯
                System.out.println("Accessing outer class field: " + outerField);
                System.out.println("This is a local inner class.");
            }
        }

        // 지역 λ‚΄λΆ€ ν΄λž˜μŠ€λŠ” λ©”μ„œλ“œ λ‚΄μ—μ„œλ§Œ 생성 및 μ‚¬μš© κ°€λŠ₯
        LocalInnerClass localInner = new LocalInnerClass();
        localInner.print();
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.display();
    }
}
λ©”μ„œλ“œ λ°–μ—μ„œλ„ μ‚¬μš©ν•΄μ•Ό ν•˜κ±°λ‚˜ λ©”μ„œλ“œ μ•ˆμ— μ •μ˜ν•˜κΈ°μ—” λ„ˆλ¬΄ κΈΈλ©΄ πŸ‘‰ 멀버 클래슀
멀버 클래슀의 μΈμŠ€ν„΄μŠ€ 각각이 λ°”κΉ₯ μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•œλ‹€λ©΄ πŸ‘‰ 비정적 멀버 클래슀
그렇지 μ•ŠμœΌλ©΄ πŸ‘‰ 정적 멀버 클래슀

쀑첩 ν΄λž˜μŠ€κ°€ ν•œ λ©”μ„œλ“œ μ•ˆμ—μ„œλ§Œ μ“°μ΄λ©΄μ„œ κ·Έ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” 지점이 단 ν•œ 곳이고 ν•΄λ‹Ή νƒ€μž…μœΌλ‘œ 쓰기에 μ ν•©ν•œ ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€κ°€ 이미 μžˆλ‹€λ©΄ πŸ‘‰ 읡λͺ… 클래슀 
그렇지 μ•ŠμœΌλ©΄ πŸ‘‰ 지역 클래슀 

 

 

 

25. ν†±λ ˆλ²¨ ν΄λž˜μŠ€λŠ” ν•œ νŒŒμΌμ— ν•˜λ‚˜λ§Œ λ‹΄κΈ°

μ»΄νŒŒμΌλŸ¬κ°€ ν•œ ν΄λž˜μŠ€μ— λŒ€ν•œ μ •μ˜λ₯Ό μ—¬λŸ¬ 개 λ§Œλ“€μ–΄ λ‚΄λŠ” 일 X
πŸ‘‰ μ†ŒμŠ€ νŒŒμΌμ„ μ–΄λ–€ μˆœμ„œλ‘œ μ»΄νŒŒμΌν•˜λ“  λ°”μ΄λ„ˆλ¦¬ νŒŒμΌμ΄λ‚˜ ν”„λ‘œκ·Έλž¨μ˜ λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” 일 X