[JAVA] 내부클래스( inner class ), 익명클래스( anonymous class )
내부클래스
내부 클래스란 클래스 안에 선언된 클래스
어느 위치에 선언하느냐에 따라서 4가지 형태가 있을 수 있다.
첫번째는 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우. 보통 중첩클래스 혹은 인스턴스 클래스라고 한다.
내부에 있는 Cal객체를 생성하기 위해서는, 밖에는 InnerExam1의 객체를 만든 후에 InnerExam1.Cal cal = t.new Cal();과 같은 방법으로 Cal객체를 생성한 후 사용한다.
public class InnerExam1{
class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam1 t = new InnerExam1();
InnerExam1.Cal cal = t.new Cal();
cal.plus();
System.out.println(cal.value);
}
}
두번째는 내부 클래스가 static으로 정의된 경우, 정적 중첩 클래스 또는 static 클래스라고 한다.
필드 선언할 때 스태틱한 필드로 선언한 것과 같다. 이 경우에는 InnerExam2객체를 생성할 필요없이 new InnerExam2.Cal() 로 객체를 생성할 수 있다.
public class InnerExam2{
static class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam2.Cal cal = new InnerExam2.Cal();
cal.plus();
System.out.println(cal.value);
}
}
세번째로는 메소드 안에 클래스를 선언한 경우, 지역 중첩 클래스 또는 지역 클래스라고 한다.
메소드 안에서 해당 클래스를 이용할 수 있다.
public class InnerExam3{
public void exec(){
class Cal{
int value = 0;
public void plus(){
value++;
}
}
Cal cal = new Cal();
cal.plus();
System.out.println(cal.value);
}
public static void main(String args[]){
InnerExam3 t = new InnerExam3();
t.exec();
}
}
내부클래스는클래스 내에 선언된 클래스로서 두 클래스가 서로 긴밀한 관계에 있기 때문에 사용한다.
내부 클래스의 장점은 다음과 같다.
내부클래스에서 외부클래스의 멤버들을 쉽게 접근할 수 있다.
코드의 복잡성을 줄일 수 있다.
내부클래스의 종류는변수의 선언 위치에 따른 종류와 같다.
내부클래스는 마치 변수를 선언하는 것과 같은 위치에 선언할 수 있으며, 변수의 선언 위치에 따라 인스턴스 변수, 클래스변수, 지역변수로 구분되는 것과 같이 내부클래스도 다음과 같이 구분되어진다.
내부클래스 종류
특징
인스턴스 클래스 ( instance class )
외부클래스의멤버변수 선언위치에 선언하며, 외부클래스의 인스턴스처럼 다뤄진다. 주로 외부클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다.
스태틱 클래스 ( static class )
외부클래스의멤버변수 선언위치에 선언하며, 외부클래스의 static멤버처럼 다루어진다. 주로 외부클래스의 static멤버, 특히 static 메소드에서 사용될 목적으로 선언된다.
지역 클래스 ( local class )
외부클래스의메소드에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
인스턴스 클래스와 스태틱 클래스는 외부클래스의 멤버변수와 같은 위치에 선언되며, 또한 멤버변수와 같은 성질을 가진다.
즉, 내부클래스가 외부클래스의 멤버와 같이 간주되고 인스턴스 멤버와 static 멤버 간의 규칙이 내부클래스에서도 똑같이 적용된다.
O/X 퀴즈 - 인스턴스 메소드에서 스태틱변수( 클래스변수 )를 사용할 수 있다. ==> O - 스태틱 메소드에서 인스턴스 변수를 사용할 수 있다. ==> X
내부클래스 중에서 스태틱 클래스만 static 멤버를 가질 수 있다.
다만final과 static이 동시에 붙은 변수는 상수이므로 모든 클래스에 정의가 가능하다.
인스턴스 멤버는 같은 클래스에 있는 인스턴스 멤버와 static멤버 모두 직접 호출이 가능하지만, static멤버는 인스턴스 멤버를 직접 호출할 수 없는 것처럼인스턴스 클래스는 외부클래스의 인스턴스 멤버를 객체 생성 없이 바로 사용할 수 있지만 스태틱 클래스는 외부클래스의 인스턴스 멤버를 객체생성없이 사용할 수 없다.
마찬가지로 인스턴스 클래스는 스태틱 클래스의 멤버들을 객체생성없이 사용할 수 있지만, 스태틱 클래스에서는 인스턴스 클래스의 멤버들을 객체생성없이 사용할 수 없다.
익명클래스
익명 중첩 클래스는 익명 클래스라고 보통 말하며, 내부 클래스이기도 하다.
익명클래스는 특이하게도 다른 내부클래스들과 달리 이름이 없다.
클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한 번만 사용될 수 있고 오직 하나의 객체만을 사용할 수 있는일회용 클래스이다.
이름이 없기 때문에 생성자도 가질 수 없으며, 조상클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 사용해서 정의하기 때문에 하나의 클래스로 상속받는 동시에 인터페이스를 구현하거나 둘 이상의 인터페이스를 구현할 수 없다.
오로지 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있다.
한 번씩만 쓰고 버릴 때 사용
익명클래스는 앞에 있는 생성자의 클래스를 상속 받고 있는 이름 없는 자식 클래스이다. 생성자의 클래스를 상속 받고 있기 때문에 업캐스팅이 되는 것이다. 그래서 익명클래스에 새로 추가하는 것들은 의미가 없다.
//추상클래스 Action
public abstract class Action{
public abstract void exec();
}
//추상클래스 Action을 상속받은 클래스 MyAction
public class MyAction extends Action{
public void exec(){
System.out.println("exec");
}
}
//MyAction을 사용하는 클래스 ActionExam
public class ActionExam{
public static void main(String args[]){
Action action = new MyAction();
action.exec();
}
}
//MyAction을 사용하지 않고 Action을 상속받는 익명 클래스를 만들어서 사용하도록 수정해 보도록 하겠습니다.
public class ActionExam{
public static void main(String args[]){
Action action = new Action(){
public void exec(){
System.out.println("exec");
}
};
action.exec();
}
}
생성자 다음에 중괄호 열고 닫고가 나오면, 해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다. 이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.