익명 클래스
클래스 중에는 단 한번만 객체로 생성하고 더 이상 재사용되지 않는 클래스가 있다. 예를 들어 이벤트 처리, 스레드 객체는 보통 프로그램에서 단 한번만 사용된다. 만약 이러한 객체의 클래스를 클래스 파일로 보관한다면 유지보수 측면에서 좋지 않다. 따라서 이런 클래스는 익명 클래스로 만드는 것이 좋다.
익명 클래스(Anonymous Class)는 이름이 없는 클래스를 뜻하며 클래스 선언과 동시에 객체를 생성하는 일회용 클래스다. 이때 생성된 객체를 익명 객체라고 한다. 그 후 더 이상 익명 클래스를 재사용할 수 없다.
익명 클래스를 선언하는 방법
익명 클래스를 선언하는 방법에는 두 가지가 있다.
- 부모를 상속받은 자식 익명 클래스 선언
- 인터페이스를 구현한 익명 클래스 선언
객체는 참조 변수로 받아 사용된다. 부모를 상속받은 익명 클래스의 익명 객체는 부모 클래스 타입의 참조 변수로 사용할 수 있다. 인터페이스를 구현한 익명 클래스의 익명 객체는 구현한 인터페이스 타입의 참조 변수로 사용할 수 있다. 익명 클래스는 이름이 없기에 타입으로 사용할 수 없다. 따라서 익명 클래스 타입 참조 변수로 익명 객체를 사용할 수 없다. 두 가지 방법의 예시를 살펴보자.
1. 부모를 상속받은 자식 익명 클래스 선언
public class Car {
public void Go() {
System.out.println("달립니다.");
}
}
import java.io.*;
import java.lang.*;
public class Main {
public static void main(String[] args) throws IOException {
Car car = new Car() {
String carName = "sonata";
@Override
public void Go() {
System.out.println(carName + " 달립니다.");
}
};
car.Go();
Object object = new Object() {
@Override
public String toString() {
return "익명 객체입니다.";
}
};
System.out.println(object.toString());
}
}
2. 인터페이스를 구현한 익명 클래스 선언
interface Car {
void Go();
void Back();
}
import java.io.*;
import java.lang.*;
public class Main {
public static void main(String[] args) throws IOException {
Car car = new Car() {
String carName = "sonata";
@Override
public void Go() {
System.out.println(carName + " 달립니다.");
}
@Override
public void Back() {
System.out.println(carName + " 후진합니다.");
}
};
car.Go();
car.Back();
}
}
익명 클래스도 사용하긴 하지만 이를 더 간략화한 람다(익명 함수)를 더 많이 사용한다.
익명 클래스 파일
.java 파일이 컴파일되면 클래스 단위로 .class 파일이 생성된다. 익명 클래스도 클래스이기에 .class 파일이 생성된다는 점을 알아두자. 특이한점은 일반적인 클래스는 클래스 이름.class로 생성되는데 반해 익명 클래스는 익명 클래스가 선언된 클래스 이름${숫자}.class 형식으로 생성된다.
Main 클래스에서 한 개의 익명 클래스가 선언되었으며 컴파일시 Main$1.class 파일이 생성되었다. 만약 Main 클래스에서 두 개의 익명 클래스가 선언되었으면 Main$1.class, Main$2.class 파일이 생성되었을 것이다.