외부 클래스와 내부 클래스가 서로 연관되어 있을 때 사용한다.
장점
1) 외부 클래스의 멤버들에 쉽게 접근할 수 있다.
2) 코드의 복잡성을 줄인다.
3) 외부적으로 불필요한 데이터를 감출 수 있다. -> 캡슐화를 달성하는데 유용
class Outer { // 외부 클래스
class Inner {
// 인스턴스 내부 클래스
}
static class StaticInner {
// 정적 내부 클래스
}
void run() {
class LocalInner {
// 지역 내부 클래스
}
}
}
내부 클래스의 종류로는 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스로 구분한다.
내부 클래스는 외부 클래스 내에 선언된다는 점을 제외하면 일반 클래스와 차이점이 없다.
인스턴스 내부 클래스는 객체 내부에 멤버의 형태로 존재하고 외부 클래스의 모든 접근 지정자의 멤버에 접근할 수 있다.
class Outer { //외부 클래스
private int num = 1; //외부 클래스 인스턴스 변수
private static int sNum = 2; // 외부 클래스 정적 변수
private InClass inClass; // 내부 클래스 자료형 변수 선언
public Outer() {
inClass = new InClass(); //외부 클래스 생성자
}
class InClass { //인스턴스 내부 클래스
int inNum = 10; //내부 클래스의 인스턴스 변수
void Test() {
System.out.println("Outer num = " + num + "(외부 클래스의 인스턴스 변수)");
System.out.println("Outer sNum = " + sNum + "(외부 클래스의 정적 변수)");
}
}
public void testClass() {
inClass.Test();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println("외부 클래스 사용하여 내부 클래스 기능 호출");
outer.testClass(); // 내부 클래스 기능 호출
}
}
// 출력값
외부 클래스 사용하여 내부 클래스 기능 호출
Outer num = 1(외부 클래스의 인스턴스 변수)
Outer sNum = 2(외부 클래스의 정적 변수)
인스턴스 내부 클래스는 외부 클래스의 내부에 위치해 있고 private 접근 제어자를 사용하고 있음에도 내부에서 외부 클래스의 인스턴스 변수와 정적 변수에 각각 접근해 해당 값을 사용하고 있다.
또 유의해야 할 것은 인스턴스 내부 클래스는 반드시 외부 클래스를 생성한 이후에 사용해야 된다.
정적 내부 클래스는 인스턴스 내부 클래스와 동일하게 클래스의 멤버 변수 위치에 정의하지만, static 키워드를 사용한다는 점에서 차이가 있다.
class Outer { // 외부 클래스
private int num = 3; // 외부 클래스의 인스턴스 변수
private static int sNum = 4;
void getPrint() {
System.out.println("인스턴스 메서드");
}
static void getPrintStatic() {
System.out.println("스태틱 메서드");
}
static class StaticInClass { // 정적 내부 클래스
void test() {
System.out.println("Outer sNum = " +sNum + "(외부 클래스의 정적 변수)");
getPrintStatic();
// num 과 getPrint() 는 정적 멤버가 아니라 사용 불가.
}
}
}
public class Main {
public static void main(String[] args) {
Outer.StaticInClass a = new Outer.StaticInClass(); //정적 이너 클래스의 객체 생성
a.test();
}
}
//출력값
Outer sNum = 4(외부 클래스의 정적 변수)
스태틱 메서드
지역 내부 클래스는 클래스의 메머가 아닌 메서드 내에서 정의되는 클래스다.
지역 변수와 유사하게 메서드 내부에서만 사용 가능하기 때문에 일반적으로 메서드 안에서 선언 후에 바로 객체를 생성해서 사용한다.
class Outer { //외부 클래스
int num = 5;
void test() {
int num2 = 6;
class LocalInClass { //지역 내부 클래스
void getPrint() {
System.out.println(num);
System.out.println(num2);
}
}
LocalInClass localInClass = new LocalInClass();
localInClass.getPrint();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test();
}
}
//출력값
5
6