내부 클래스(Inner Class)
특징
- 클래스 내부에 선언하는 클래스로 중첩 클래스라고도 부른다.
- HAS-A 관계에 있는 클래스(클래스 내부에서 다른 클래스의 객체를 선언하는것)가 해당 클래스에서만 사용될 경우 주로 사용한다.
- 캡슐화에 용이하다.
- static final 변수만 가질 수 있다.
- 외부 클래스 객체가 있어야 생성이 가능하다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class outer1{
class InstanceInner{
int x = 1;
static final int CONSTANT_VAR = 1000; // static 변수는 final만 가능하다.
void innerMethod(){
int x = 0;
System.out.println(x); //0
System.out.println(this.x); //1
System.out.println(outer1.this.x); //2
System.out.println(outer1.y); //3
}
}
private int x = 2;
private static int y = 3;
}
클래스 내부 클래스(Class Inner Class)
특징
- 클래스 영역에 static 키워드와 함께 선언된 내부 클래스.
- 외부 클래스 객체가 없어도 생성이 가능하다.
- 외부 클래스의 모든 것에 접근 가능하다.
- static 멤버 변수를 가질 수 있다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
class outer2{
static class ClassInner{
int innerVar = 1;
static int staticInnerVar = 100;
void innerMethod(){
// static 내부 클래스가 생성되는 시점에는 외부 객체가 존재하지 않는다.
// 따라서 외부 변수에 접근하기 위해서는 외부 객체를 생성한 후 접근해야한다.
outer2 outer = new outer2();
System.out.println(outer.outerVar);
}
}
private int outerVar = 2;
}
로컬 이너 클래스(Local Inner Class)
특징
- 클래스 영역이 아닌 로컬 영역에서 선언된 클래스이다.
- static 변수 지정이 불가능하다. static final만 가능하다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class LocalInnerClass {
int x = 1;
public void methodA(){
class LocalInner{
int x = 2;
// static int z = 4 ->
// 불가능하다. static 변수는 class영역에 저장되어야하는데 LocalInner 클래스가 스택에 저장되므로 상충된다.
static final int z = 4; // final은 더이상 수정이 되지 않는 상수풀에 영속적으로 존재하게 되므로 가능하다.
void innerMethod(){
System.out.println(x); //2
System.out.println(this.x); //1
}
}
}
}
익명 클래스(Anonymous Inner Class)
특징
- 이름 없이 선언 즉시 한번 사용이 가능하다.
- 주로 추상클래스, 인터페이스 구현에 사용한다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
interface IFoo{
void run();
}
class Foo implements IFoo{
@Override
public void run() {
}
}
public class AnonymousInnerClass {
static void useIFoo(IFoo iFoo){
iFoo.run();
}
public static void main(String[] args) {
Foo foo = new Foo();
useIFoo(foo); // 다형성으로 인해서 사용 가능하다. foo->IFoo
useIFoo(new IFoo(){
@Override
public void run() {
}
});
// 구현해야하는 함수가 하나인 경우에만 사용할 수 있다.
useIFoo(()-> {
System.out.println("Lambda 식 사용");
});
}
}