일반적으로 자바 이론 공부를 하다보면 추상클래스는 객체 생성이 불가능하다고 설명합니다. 오늘은 이와 관련해서 개인적으로 궁금했던 몇 가지를 정리했습니다.
관련 키워드 : 참조 배열, 익명 클래스
추상 클래스 Animal
public abstract class Animal {
abstract void bark();
}
구현 클래스 Cat
public class Cat extends Animal{
@Override
void bark() {
System.out.println("냥냥");
}
}
구현 클래스 Dog
public class Dog extends Animal{
@Override
void bark() {
System.out.println("멍멍");
}
}
오늘 다뤄볼 예제 클래스들 입니다. 복잡한 기능은 없고 간단하게 추상 메서드를 Override를 하고 있습니다.
main 메서드
public static void main(String[] args) {
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
Animal animal = new Animal() {
@Override
void bark() {
System.out.println("이게 뭐야");
}
};
animals[0].bark();
animals[1].bark();
animal.bark();
}
main에서는 추상 클래스인 Animal의 참조 배열인 animals를 선언합니다. 그리고 animals 배열 각각에 Dog나 Cat 객체를 생성해주죠.
참조 배열?? 추상 클래스의 객체??
여기서 첫 번째 의문이 들었던 점은. 추상 클래스는 new 키워드를 못쓴다고 들었는데 저기서는 쓸 수 있다는 점이 궁금했습니다. 위에서도 언급했지만 animals는 참조 배열입니다. Animal 클래스의 객체를 직접 생성하는 것이 아니라 그 클래스의 객체를 저장할 수 있게 하는 배열이에요.
참조 배열이란 객체의 주소를 저장하는 배열입니다. 예시에서는 Animal 객체의 주소를 저장하기 위한 배열이 되겠군요. 객체는 필드와 메서드로 구성된 일종의 실체를 가지고 있습니다. 객체는 메모리에 생성되어 실행 중에 존재하게 됩니다. 참조 배열은 객체의 주소를 저장하지만 그렇다고 해서 객체인 것은 아니죠.
결론을 말씀드리면 추상 클래스에 무조건 new 키워드를 쓰지 못하는 것은 아닙니다. 그게 참조 배열인 경우에는 객체 생성과는 달리 제대로 쓸 수 있습니다.
추상 클래스는 언제나 객체 생성을 못하는가??
제가 쓴 예제 코드에서 Animal animal = new Animal() 부분을 봐주세요. 원래는 메서드의 구현체가 존재하지 않기에 에러가 생기게 됩니다. 그러나 제가 작성한 코드에서는 객체 생성과 동시에 메서드를 구현하고 있죠?? 이런 경우에는 에러가 발생하지 않습니다.
자바에서는 익명 클래스를 제공하고 있습니다. 추상 클래스로 익명 객체를 생성하면서 동시에 메서드를 오버라이딩해준다면 이때는 객체로 만들 수 있습니다. 따라서 현재 animal은 Animal 클래스의 익명 클래스 객체가 됩니다. 이런 방식으로 익명 클래스를 활용하면 추상 클래스도 인스턴스화가 가능해집니다.
'Java' 카테고리의 다른 글
[Java] 어노테이션 정리 (0) | 2021.06.22 |
---|---|
[JAVA] Enum 열거형 정리 (0) | 2021.06.07 |
[JAVA] 멀티쓰레드 프로그래밍 (0) | 2021.06.02 |
[Java] 예외처리 (0) | 2021.05.18 |
[Java] 인터페이스에 대하여 (0) | 2021.05.10 |