익명 클래스

박태현·2025년 4월 24일

Java

목록 보기
12/17

내부( Inner ) 클래스의 일종으로 이름 없는 클래스를 의미합니다.

재사용되지 않고, 일회용으로 사용하는 객체

클래스를 익명으로 사용하는 것이 아니라, 이미 정의된 클래스의 멤버를 재정의 하여 사용할 때 일회성으로 사용하는 기법

익명 클래스는 이름이 없기에 생성자를 가질 수 없음, 가질 필요도 없고


보통 어느 클래스의 자원을 상속 받아 재정의하여 이를 사용하기 위해서는 자식 클래스를 생성하고, 상속을 통해 객체 인스턴스를 초기화 하여 사용이 가능하지만. 익명 클래스는 클래스 정의와 동시에 객체를 생성할 수 있음

즉, 클래스 선언과 객체의 생성을 동시에 하기에 단 한번만 사용됨

ex) 어느 메서드에서 부모 클래스의 자원을 상속받아 재사용하여 사용 할 자식 클래스가 한 번만 사용되고 말거라면 굳이 클래스를 만들기보다는 지역변수처럼 정의하고 사용하는 것

class Animal {
    public String bark() {
        return "동물이 웁니다";
    }
}

public class Main {
    public static void main(String[] args) {
				# 클래스 정의와 객체 생성을 동시에 진행
        Animal dog = new Animal() {
        	@Override
            public String bark() {
                return "개가 짖습니다";
            }
        }; // 익명 클래스는 끝에 세미콜론을 반드시 붙여야함
        	
        dog.bark();
    }
}

기존의 자식 클래스에 상속시켜 사용하지 않고 익명으로 인라인으로 한 번에 선언하여 사용

익명 클래스의 유의점


익명 클래스 방식으로 선언한다면 오버라이딩 한 메서드 사용만 가능하고, 새로 정의한 메서드는 외부에서 사용이 불가능함

class Animal {
    public String bark() {
        return "동물이 웁니다";
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Animal() {
        	@Override
            public String bark() {
                return "개가 짖습니다";
            }
            
            public void method() {
			        sout("aaa");
			      }
        }; 
        
        dog.bark();
        dog.method(); // error : 부모 클래스에는 이 메서드가 존재하지 않기 때문
    }
} 

익명 클래스 선언 위치


[ 클래스의 필드로 이용 ]

특정 클래스 내부에서 여러 메소드에서 이용될 때

class Animal { ... }

class Creature {
    Animal dog = new Animal() {
        public String bark() {
            return "멍멍";
        }
    };

    public void method() {
        dog.bark();
    }
}

[ 지역 변수로 이용 ]

class Animal { ... }

class Creature {
	// ...
    
    public void method() {
    	// 지역 변수같이 클래스를 선언하여 일회용으로 사용
        Animal dog = new Animal() {
            public String bark() {
                return "멍멍";
            }
        };
        
        dog.bark();
    }
}

[ 메서드의 파라미터로 이용 ]

class Animal { ... }

class Creature {
	// ...
    
    public void method(Animal dog) { // 익명 객체 매개변수로 받아 사용
        dog.bark();
    }
}

public class Main {
    public static void main(String[] args) {
        Creature monster = new Creature();
        
        // 메소드 아규먼트에 익명 클래스 자체를 입력값으로 할당
        monster.method(new Animal() {
            public String bark() {
                return "멍멍";
            }
        });
    }
}

인터페이스에서의 익명 구현 객체


Java에서 익명 클래스를 사용하여 인터페이스를 바로 구현하여 생성한 객체를 흔히 익명 구현 객체라고 부릅니다.

익명 클래스를 사용하는 때는 거의 없지만, 인터페이스를 익명 객체로 선언하여 사용할 때 유용하게 쓰입니다.

당연히 추상 클래스로도 이렇게 사용 가능

// 인터페이스
interface IAnimal {
    public String bark(); // 추상 메소드
    public String run();
}

public class Main {
    public static void main(String[] args) {
        
        IAnimal dog = new IAnimal() {
            @Override
            public String bark() {
                return "개가 짖습니다";
            }
            
            @Override
            public String run() {
                return "개가 달립니다";
            }
        };
        
        // 인터페이스 구현 객체 사용
        dog.bark();
        dog.run();
    }
}

익명 구현 객체의 활용


// 연산식을 추상화한 인터페이스
interface Operate {
    int operate(int a, int b);
}
// 계산을 담당하는 클래스
class Calculator {
    private final int a;
    private final int b;
	
    public Calculator(int a, int b) {
        this.a = a;
        this.b = b;
    }

    // 인터페이스 타입을 매개변수로 받는 메소드 (다형성)
    public int caculate(Operate op) {
        return op.operate(this.a, this.b); // 매개변수 객체의 메서드 실행하여 리턴
    }
}
public class Main {
    public static void main(String[] args) {
        // 계산할 두 수
        int num1 = 20;
        int num2 = 10;

        Calculator calculator = new Calculator(num1, num2);

	      int result = calculator.caculate(new Operate() {
            public int operate(int a, int b) {
                return a + b;
            }
        });

        System.out.println(result); // 30

				int result2 = calculator.caculate(new Operate() {
            public int operate(int a, int b) {
                return a - b;
            }
        });

        System.out.println(result2); // 10
    }
}

코드 구조의 유연성과 확장성을 높이기 위해 Calculate 안에서 연산 함수를 만들지 않고 위와 같이 사용

새로운 연산이 필요하면 그때마다 Calculator 클래스를 계속 수정해야 하는데, 이는 OCP를 위배하고, 유지보수가 어려우므로 익명 클래스를 사용

익명 클래스의 한계


  • 재사용할 수 없음

  • 코드의 길이가 길어진다면 가독성이 안좋아짐

  • 클래스의 이름이 없기에 생성자 정의 불가

  • 익명 클래스는 하나의 클래스 또는 하나의 인터페이스만 구현할 수 있습니다. ( 다중 구현 불가 )

람다 표현식


Operate operate = (a, b) -> a + b;

Operate가 함수형 인터페이스( 메서드 하나 )라면, 위와 같은 람다식으로 변경할 수 있습니다.

람다 표현식을 쓸 수 있는 경우 : 함수형 인페이스에서만 사용 가능

profile
꾸준하게

0개의 댓글