반응형
내부 클래스 (inner class)
- 클래스 내부에 선언한 클래스로 이 클래스를 감싸고 있는 외부 클래스와 밀접한 연관이 있는 경우가 많고 다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스로 선언해서 사용함
- 중첩 클래스라고도 함
- 내부 클래스의 종류: 인스턴스 내부클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명(anonymous) 내부 클래스
인스턴스 내부 클래스
- 내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)
- 외부 클래스가 생성된 후 생성됨(정적 내부 클래스와 다름)
- private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음
package ch51;
class OutClass {
private int num = 0;
private static int sNum = 20;
private InClass inClass;
public OutClass() {
inClass = new InClass();
}
// out class 가 생성되고 생성
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();
}
}
정적 내부 클래스
- 외부 클래스 생성과 무관하게 사용할 수 있음
- 정적 변수, 정적 메서드 사용
- 정적 내부 클래스 예
package ch51;
class OutClass {
private int num = 0;
private static int sNum = 20;
private InClass inClass;
public OutClass() {
inClass = new InClass();
}
// out class 가 생성되고 생성
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();
}
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 + "(내부 클래스의 스테틱 변수)");
}
}
}
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();
// 외부 인스턴스 변수 사용 불가
OutClass.InStaticClass sInclass = new OutClass.InStaticClass();
sInclass.inTest();
System.out.println();
// 스태틱 변수들만 사용가능
OutClass.InStaticClass.sTest();
}
}
지역 내부 클래스
- 지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스
- 메서드의 호출이 끝나면 메서드에 사용된 지역변수의 유효성은 사라짐
- 메서드 호출 이후에도 사용해야 하는 경우가 있을 수 있으므로 지역 내부 클래스에서 사용하는 메서드의 지역 변수나 매개변수는 final로 선언됨
package ch51;
class Outer2{
int outNum = 100;
static int sNum = 200;
Runnable getNuRunnable(int i) {
int num = 10;
class MyRunnable implements Runnable {
int localNum = 100000;
@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 = out.getNuRunnable(100);
runner.run();
}
}
MyRunnable 클래스를 사용하려면 직접 생성하는 것이 아닌 getRunnable()메서드를 호출하여 생성된 개체를 반환 받아야 함
익명 내부 클래스
- 이름이 없는 클래스 (위 지역 내부 클래스의 MyRunnable) 클래스 이름은 실제로 호출되는 경우가 없음
- 클래스의 이름을 생략하고 주로 하나의 인터페이스나 하나의 추상 클래스를 구현하여 반환
- 인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 클래스를 생성하거나 지역 내부 클래스의 메서드 내부에서 생성아여 반환 할 수 있음
- widget의 이벤트 핸들러에 활용됨
package ch51;
class Outer2{
int outNum = 100;
static int sNum = 200;
Runnable getNuRunnable(int i) {
int num = 10;
// class MyRunnable implements Runnable {
//
// int localNum = 100000;
//
// @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();
// 익명 inner class로 변환
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 + "(외부 클래스 정적 변수)");
}
};
}
// 익명 inner class(많이 사용됨)
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Runnable calss");
}
};
}
public class AnonymousInnerTest {
public static void main(String[] args) {
Outer2 out = new Outer2();
Runnable runner = out.getNuRunnable(100);
runner.run();
out.runnable.run();
}
}
반응형
'언어 > JAVA' 카테고리의 다른 글
스트림(Stream) (0) | 2021.05.08 |
---|---|
람다식 (0) | 2021.05.08 |
Map 인터페이스 (0) | 2021.05.02 |
Comparable, Comparator 인터페이스 (0) | 2021.05.02 |
Set 인터페이스 (0) | 2021.05.02 |