내부 클래스

내부 클래스

종류

인스턴스(instance) 내부 클래스

  • 인스턴스 변수와 생성 위치, 방법, Scope가 동일하다.
  • 내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)
  • 외부 클래스가 생성된 후 생성됨
  • private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있다.
    • 문법적으로는 가능하지만 잘 사용하지 않는다.
예제 코드 확인하기
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
29
30
31
32
33
34
35
36
37
38
39
package ch01;

class OutClass{

private int num = 10;
private static int sNum = 20;
private InClass inClass;

public OutClass(){
inClass = new InClass();
}

class InClass{
int iNum = 100;

void inTest() {
System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)");
System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수)");
System.out.println("InClass inNum = " + iNum + "(내부 클래스의 인스턴스 변수)");
}

}

public void usingClass(){
inClass.inTest();
}
}

public class InnerTest {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.usingClass();
System.out.println("=========");
OutClass.InClass inner = outClass.new InClass();
inner.inTest();
}
}


정적(static) 내부 클래스

  • 정적 변수와 정적 메서드를 사용한다.
  • 내부 클래스의 인스턴스, 스태틱 변수, 외부 클래스의 스태틱 변수를 사용할 수 있다.
  • 외부 클래스 생성과 무관하게 사용할 수 있다.
  • 외부 클래스가 생성되지 않아도 사용할 수 있기 때문에 정적 내부 클래스에서 외부 클래스의 인스턴스 변수를 사용할 수 없다.
  • 정적 내부 클래스의 정적 메서드는 스태틱 변수만 사용할 수 있다.
예제 코드 확인하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static class InStaticClass{
int iNum = 100;
static int sInNum = 200;

void inTest() {
System.out.println("inClass num = " +iNum + "(외부 클래스의 인스턴스 변수)");
System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수)");
System.out.println("InClass inNum = " + sInNum + "(내부 클래스의 인스턴스 변수)");
}

static void sTest(){
System.out.println("OutClass sNum = " + sNum + "(외부 클래스의 스태틱 변수)");
System.out.println("InClass inNum = " + sInNum + "(내부 클래스의 인스턴스 변수)");
}
}

지역(local) 내부 클래스

  • 지역 변수와 같이 메서드 내부에서 정의하여 사용한다.
  • 메서드의 호출이 끝나면 메서드에 사용된 지역변수의 유효성은 사라짐

    메서드 호출 이후 반환이 되어도 메서드의 지역 변수를 클래스를 통해 사용할 수 있으므로 final로 처리한다.

예제 코드 확인하기
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
29
30
31
32
33
34
35
36
37
38
class Outer2{

int outNum = 100;
static int sNum = 200;
// 메서드
Runnable getRunnable(final int i){
final int num = 10;
// 지역 내부 클래스
class MyRunnable implements Runnable{
int localNum = 1000;
// 재정의
@Override
public void run() {

System.out.println("i =" + i);
System.out.println("num = " +num);
System.out.println("localNum = " +localNum);

System.out.println("outNum = " + outNum + "(외부 클래스 인스턴스 변수)");
System.out.println("Outter.sNum = " + Outer2.sNum + "(외부 클래스 정적 변수)");

}
}
return new MyRunnable();
}
}

public class AnonymousInnerTest {
public static void main(String[] args) {

Outer2 out = new Outer2();
// 메서드가 Runnable한 값을 runner에 return해주고 해제되었다.
Runnable runner = out.getRunnable(100);
// 해제된 이후 지역 내부 클래스의 메서드 사용
// final로 선언해주었기 때문에
runner.run();
}
}

익명(Anonymous) 내부 클래스

  • 이름이 없는 클래스
    • 지역 내부 클래스의 예시코드에서 클래스 이름 MyRunnable은 실제로 호출되지 않으므로 이를 생략한다.
    • 하나의 인터페이스나 하나의 추상 클래스를 구현하여 반환한다.
예제 코드 확인하기
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package ch01;

class Outer2{

int outNum = 100;
static int sNum = 200;
// 메서드
Runnable getRunnable(final int i){
final int num = 10;
// 익명 내부 클래스 (바로 return값을 입력)
return new Runnable(){
int localNum = 1000;
// 재정의
@Override
public void run() {

System.out.println("i =" + i);
System.out.println("num = " +num);
System.out.println("localNum = " +localNum);

System.out.println("outNum = " + outNum + "(외부 클래스 인스턴스 변수)");
System.out.println("Outter.sNum = " + Outer2.sNum + "(외부 클래스 정적 변수)");

}
};
}
// runnable을 생성해서 바로 구현
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Runnable class");
}
};
}

public class AnonymousInnerTest {
public static void main(String[] args) {

Outer2 out = new Outer2();
Runnable runner = out.getRunnable(100);
runner.run();

out.runnable.run();
}
}

Author

Inwoo Jeong

Posted on

2021-08-24

Updated on

2021-09-09

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.

댓글