goal
java 내부 클래스(inner class)에 대해서 이해한다.
1 ] 내부클래스 (inner class)
class Outside {
// ...
class Inner {
//...
}
}
1. 개념
내부클래스는 클래스 내에 선언된 클래스이다.
2. 사용목적
밖의 클래스와 내부 클래스가 긴밀한 관계에 있기 때문에
3. 장점
- 내부클래스에서, 외부 클래스의 멤버(필드)들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다.
- 외부에서 불필요한 클래스를 은닉함으로써 코드의 복잡성을 줄일 수 있다. (캡슐화)
4. inner class의 종류
- 정적 클래스 (static class)
- 인스턴스 클래스 (instance class)
- 지역 클래스 (local class)
- 익명 클래스 (anonymous class)
[1] static class
- 외부 클래스의 field 선언부에 위치하고 static 키워드가 붙은 내부 클래스.
- static이 붙어있기 때문에 외부 클래스의 객체를 생성하지 않고도 내부 클래스의 객체를 생성할 수 있다.
- 내부에는 instance member와, static member 모두 선언 할 수 있다.
class Outside {
satic class StaticInner {
int data;
static int data2;
}
}
Outside.StaticInner staticInner = new Outside.StaticInner();
※ class에 붙는 static과 멤버에 붙는 static의 의미 차이
우선 둘의 의미는 다름을 인지하자. 각각의 의미는 아래와 같다.
- 멤버에 붙는 static : 정적 메모리를 잡아준다는 의미로, 컴파일 타임에 컴파일러가 메모리 할당하기 때문에 객체 생성없이도 사용 가능하다.
- class에 붙는 static : 외부 클래스의 객체 생성없이 내부 클래스의 객체를 생성할 수 있다는 의미
[2] instance class
- 외부 클래스의 field 선언부에 위치하고 static 키워드가 없는 내부 클래스
- 외부 클래스의 멤버이기 때문에 외부 클래스의 객체 먼저 생성한 후 내부 클래스의 객체를 생성하여 사용해야한다.
- instance class 내부에는 instance member만 선언가능하다 ∴ static member는 선언 불가하다.
- 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언한다.
class Outside {
class InstanceInner {
int data;
}
}
/*
inner class에서 instance class의 객체를 생성하기 위해서는
외부클래스 객체 생성이 먼저 이루어져야한다.
*/
Outside outside = new Outside(); // 외부클래스 객체생성
Outside.InstanceInner instanceInner = new Outside.InstanceInner(); // 내부클래스 객체생성
[3] local class
- 외부 클래스의 메소드 내부에 위치하는 클래스 (지역변수와 같은 성질을 지닌다.)
- 접근 제한자와 static을 붙일 수 없다. 메소드 내부에서만 사용되므로 접근을 제한할 필요가 없고,
애초에 메소드 내에는 static 멤버를 선언할 수 없기 때문이다.
class Outside {
static void method1() {
class LocalInner {
int data;
}
LocalInner localInner = new LocalInner();
localInner.data = 10;
}
}
[4] anonymous class
참고 블로그 : 익명클래스 사용방법, https://yookeun.github.io/java/2017/01/24/java-anonymousclass/, 와이케이의 마구잡이
- anonymous class는 클래스를 정의하는 동시에 객체를 생성할때 만들어지는 클래스이다.
- 이름이 없는 클래스이다.
- Interface, Class 모두 익명 클래스로 객체를 만들 수 있다.
- 한 번만 객체를 만들 때 사용한다. (일회용 클래스) 즉, 프로그램에서 일지적으로 한번만 사용되고 버려지는 객체, 이 말은 다른 뜻으로 재사용이 되지 않는다는 것과 같다.
- 사용하는 이유는 아래와 같다.
- 한 번만 사용되고 버려질 클래스를 대체하여 사용
∴ class파일을 만드는 것을 억제하여 저장공간의 이점을 가진다.
- 한 번만 사용되고 버려질 클래스를 대체하여 사용
// 익명클래스 만드는 형식
부모클래스 인스턴스 = new 부모클래스() {
};
public class Person {
void whoAmI() {
System.out.println("나는 Person 이다.");
}
}
public static void main(String[] args) {
Person p = new Person() {
String name = "Kim";
@Override // 재정의
void whoAmI() {
System.out.println("나는 " + name + " 이다.");
}
};
p.whoAmI(); // 나는 Kim 이다.
}
※ 익명클래스 사용의 주의점
- 익명클래스에 생성된 메소드나 필드는 익명클래스 밖에서는 접근할 수 없다.
-
Person p = new Person() { String name = "Kim"; public void callMe() { System.out.println("Call callMe method"); } @Override void whoAmI() { System.out.println("나는 " + name + " 이다."); } }; //p.callMe(); //실행되지 않는다. 에러. p.whoAmI();
- callme() 메소드는 익명클래스에서 만들어진 클래스이다.
-
※ 익명클래스 알고가기
- 익명클래스는 매개변수로 전달이 가능하다.
-
public static void walk2(Person p) { p.whoAmI(); }
-
walk2(new Person(){ String name = "Lee"; @Override void whoAmI() { System.out.println("나는 " + name + " 이다."); } });
-
- 인터페이스도 익명구현클래스로 만들면 편하게 사용이 가능하다.
-
public interface Remocon { public void on(); public void off(); }
-
public class Machine { Remocon tv = new Remocon() { @Override public void on() { System.out.println("TV을 켭니다"); } @Override public void off() { System.out.println("TV을 끕니다."); } }; }
- 실행은 아래와 같다.
-
Machine machine = new Machine(); machine.tv.on(); //TV를 켭니다. machine.tv.off(); //TV를 끕니다.
-
-
- 익명클래스를 메소드나 익명클래스를 매겨변수로 받는 메소드로 만들 수 있다. (두가지 모두 구현)
-
public void radioWork() { Remocon radio = new Remocon() { @Override public void on() { System.out.println("Radio을 켭니다"); } @Override public void off() { System.out.println("Radio을 끕니다."); } }; radio.on(); radio.off(); } public void machineWork(Remocon remocon) { remocon.on(); remocon.off(); }
-
machine.radioWork(); machine.machineWork(new Remocon(){ @Override public void on() { System.out.println("컴퓨터를 켭니다."); } @Override public void off() { System.out.println("컴퓨터를 켭니다."); } });
-
'Java > java' 카테고리의 다른 글
java :) Arrays의 다양한 메소드 정리하기 (0) | 2022.04.23 |
---|---|
java :) StringBuffer (0) | 2022.04.23 |
java :) interface와 abstract의 공통점과 차이점 (0) | 2022.04.22 |
java :) generic method (0) | 2022.03.14 |
java :) generic class의 이해 (0) | 2022.03.13 |