내부 클래스
- 클래스 내부에 선언한 클래스로 이 클래스를 감싸고 있는 외부 클래스와 밀접한 연관이 있는 경우가 많고, 다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스로 선언해서 사용함
- 중첩 클래스라고도 함
- 내부 클래스의 종류
인스턴스 내부 클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명(anonymous) 내부 클래스
인스턴스 내부 클래스
- 내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)
- 외부 클래스가 생성된 후 생성됨 (정적 내부 클래스와 다름)
- private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음
OutClass outClass = new OutClass();
OutClass.InClass inClass = outClass.new InClass();
InnerTest.java
class OutClass{
private int num = 10;
private static int sNum = 20;
private InClass inClass;
public OutClass(){
inClass = new InClass();
}
private class InClass{ // 내부 클래스
int iNum = 100;
void inTest() {
System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)" );
System.out.println("OutClass sNum = " +sNum + "(외부 클래스의 스태틱 변수)" );
System.out.println("InClass iNum = " +iNum + "(내부 클래스의 인스턴스 변수)" );
}
}
public void usingClass() {
inClass.inTest();
}
}
public class InnerTest {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.usingClass();
}
}
정적 내부 클래스
- 외부 클래스 생성과 무관하게 사용할 수 있음
- 정적 변수, 정적 메서드 사용
class OutClass{
private int num = 10;
private static int sNum = 20;
private InClass inClass;
public OutClass(){
inClass = new InClass();
}
private class InClass{ // 내부 클래스
int iNum = 100;
void inTest() {
System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)" );
System.out.println("OutClass sNum = " +sNum + "(외부 클래스의 스태틱 변수)" );
System.out.println("InClass iNum = " +iNum + "(내부 클래스의 인스턴스 변수)" );
}
}
public void usingClass() {
inClass.inTest();
}
static class InStaticClass{ // 정적 내부 클래스
int iNum = 100;
static int sInNum = 200;
void inTest() {
// System.out.println("OutClass num = " +num + "(외부 클래스의 인스턴스 변수)" ); 외부클래스 상관 없이 생성 될 수 있기 때문에 오류
System.out.println("InClass iNum = " +iNum + "(내부 클래스의 인스턴스 변수)" );
System.out.println("OutClass sNum = " +sNum + "(외부 클래스의 스태틱 변수)" );
System.out.println("InClass sInNum = " +sInNum + "(내부 클래스의 스태틱 변수)" );
}
static void sTest() {
// System.out.println("InClass iNum = " +iNum + "(내부 클래스의 인스턴스 변수)" ); InStaticClass가 생성 안되고 메모리에 올라가기 때문에 에러
System.out.println("OutClass sNum = " +sNum + "(외부 클래스의 스태틱 변수)" );
System.out.println("InClass sInNum = " +sInNum + "(내부 클래스의 스태틱 변수)" );
}
}
}
public class InnerTest {
public static void main(String[] args) {
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
sInClass.inTest();
System.out.println();
OutClass.InStaticClass.sTest(); // 클래스 생성 들과 무관 하게 호출 가능
}
}
지역 내부 클래스
- 지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스
- 메서드의 호출이 끝나면 메서드에 사용된 지역변수의 유효성은 사라짐
- 메서드 호출 이후에도 사용해야 하는 경우가 있을 수 있으므로 지역 내부 클래스에서 사용하는 메서드의 지역 변수나 매개 변수는 final로 선언
class Outer2{
int outNum = 100;
static int sNum = 200;
Runnable getRunnable(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 AnonumousInnerTest {
public static void main(String[] args) {
Outer2 out = new Outer2();
Runnable runner = out.getRunnable(100);
runner.run();
}
}
익명 내부 클래스
- 이름이 없는 클래스 (위 지역 내부 클래스의 MyRunnable 클래스 이름은 실제로 호출되는 경우가 없음)
- 클래스의 이름을 생략하고 주로 하나의 인터페이스나 하나의 추상 클래스를 구현하여 반환
- 인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 클래스를 생성하거나 지역 내부 클래스의 메서드 내부에서 생성하여 반환 할 수 있음
- widget의 이벤트 핸들러에 활용
class Outer2{
int outNum = 100;
static int sNum = 200;
Runnable getRunnable(int i) { // 클래스를 쓰레드 선언 할 때 사용 하는 인터페이스
final int num = 10;
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 = new Runnable() {
@Override
public void run() {
System.out.println("Runnable class");
}
};
}
public class AnonumousInnerTest {
public static void main(String[] args) {
Outer2 out = new Outer2();
Runnable runner = out.getRunnable(100);
runner.run();
out.runnable.run();
}
}
'JAVA' 카테고리의 다른 글
| [JAVA] 함수형 인터페이스와 람다식 구현하여 사용하기 (0) | 2023.09.10 |
|---|---|
| [JAVA] 람다식 (1) | 2023.09.10 |
| [JAVA] 쌍(pair)으로 자료를 관리하는 Map 인터페이스를 구현한 클래스와 그 활용 (1) | 2023.09.01 |
| [JAVA] 중복되지 않게 자료를 관리하는 Set 인터페이스를 구현한 클래스와 그 활용 (0) | 2023.08.28 |
| [JAVA] Collection 요소를 순회하는 Iterator (1) | 2023.08.28 |