익명 클래스란
•
익명 객체(익명 클래스)는 말 그래도 이름이 없는 객체 혹은 이름이 없는 클래스로 무명 클래스라고도 불린다.
•
이름이 없다는 것은 다시 불릴 필요가 없기 때문에 기억되지 않는다는 의미로, 프로그램에서 일시적으로 한 번만 사용되고 버려지는 객체를 말한다. 재사용 되지 않기 때문에 확장성이 좋지 못하다.
•
UI 이벤트처리나 스레드 객체 등 단발성 이벤트를 처리하는 경우나, 비즈니스 로직이 제각각이라 재사용성이 없고 확장성을 활용하는 것이 유지보수에서 더 불리할 경우에 사용된다.
•
클래스를 별도로 만들 필요없이 코드에서 익명 객체를 생성 및 정의하여 사용되고 소멸하기 때문에, 덜 귀찮고 유지보수에 유리하다.
익명 클래스 구현 방법
public class Insect {
void attack() {
System.out.println("공격하기");
}
}
Java
복사
1.
필드의 초기값으로 구현하기
public class Anonymous {
Insect spider1 = new Insect() {
String name = "거미1";
void cobweb() {
System.out.println(name + "거미줄 치기");
}
@Override
void attack() {
System.out.println(name + "공격하기");
}
}
}
Java
복사
2.
로컬변수의 초기값으로 구현하기
public class Anonymous {
void method1() {
Insect spider2 = new Insect() {
String name = "거미2";
void cobweb() {
System.out.println(name + "거미줄 치기");
}
@Override
void attack() {
System.out.println(name + "공격하기");
}
}
spider2.attack();
}
}
Java
복사
3.
매개변수로 구현하기
public class Anonymous {
void method2(Insect spider3) {
spider3.attack();
}
}
Java
복사
•
익명 클래스 사용하기
public class AnonymousExample {
public static void main(String[] args) {
Anonymous a = new Anonymous();
//방법 1 : 익명객체 필드 사용
a.spider1.attack();
//방법2 : 익명객체 로컬 변수 사용
a.method1();
//방법3 : 매개변수로 익명개체 사용
a.method2(new Insect(){
String name = "타란툴라";
//거미줄을 치다.
void cobweb(){
System.out.println("그냥 마구잡이로 친다.");
}
@Override
void attack() {
System.out.println(name + " 공격 안하고 후퇴한다..");
};
});
//익명객체 내부에서 새롭게 정의된 필드,메서드는 부모객체로 생성된 spider1에서 접근할 수 없음!!!
a.spider1.name = "왕거미"; //익명객체에서 새롭게 정의된 필드 (접근불가)
a.spider1.cobweb(); //익명객체에서 새롭게 정의된 메서드 (접근불가)
}
}
Java
복사
익명 구현 객체
•
위의 예시들은 Insect라는 클래스를 두고 그를 상속하여 익명 클래스를 생성하는 상속 익명 객체이다.
•
익명 클래스의 진가는 인터페이스를 익명 객체로 선언하여 사용하는 경우이다. 익명 클래스는 일회성 오버라이딩의 용도로 사용되는데, 추상화 구조인 인터페이스를 일회용으로 구현하여 사용하는 경우 시너지가 매우 잘 맞는다.
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();
}
}
Java
복사
•
위를 보면 인터페이스를 클래스 생성자처럼 초기화하여 인스턴스화 한 것처럼 보이지만, 사실 자식 클래스를 생성해 implements하고 클래스를 초기화 한 것과 다름없다.
•
추상 클래스(abstract class)도 이런 방식으로 익명 구현 객체 생성이 가능하다.
•
상속 익명 객체와의 차이점은 익명 구현 객체는 인터페이스에서 메소드 정의를 통해 사용해야하는 규약으로 규격화에 도움이 된다는 점이다.
•
익명 클래스 기법은 자바 문법을 간결하게 만드는데 초점을 두고, 이는 java 8의 람다식 문법과 매우 잘 어울린다.
Operate operate = new Operate() {
public int operate(int a, int b) {
return a + b;
}
};
// 람다식으로 줄이기
Operate operate = (a, b) -> {
return a + b;
};
// 더 짧게 줄이기 (리턴 코드만 있다면 생략이 가능)
Operate operate = (a, b) -> a + b;
Java
복사
•
다만 람다식을 통해 익명 클래스를 사용하려면, default 메서드 제외하고 단 하나의 추상 메서드만 선언되어 있는 인터페이스만 가능하다.
•
인터페이스의 가장 큰 본질은 다중 상속(구현)이 가능하다는 것인데, 익명 구현 객체는 오직 하나의 인터페이스만 구현하여 객체를 생성한다는 한계가 있다.