728x90
728x90

* 이 글은 제가 공부하기 위해 최대한 사실에 입각해 내용을 적으려고 하지만 일부 내용들이 정확하지 않을 수 있습니다.

   혹시나 잘못된 부분이 있으면 너그럽게 이해해주시고 피드백 부탁드려요!


10장 내부클래스

10.1 내부클래스

내부(중첩) 클래스의 구조는 아래와 같다.

class 클래스 명 {
    class 내부 클래스명 {
        ...
    }
}

내부 클래스는 크게 두가지로 구분 되는데, 하나는 클래스의 멤버로 정의되는 멤버 클래스와 메서드 내부에 정의되는 로컬 클래스로 나눠진다. 멤버 클래스는 객체로 생성된 후 어디서든 다시 사용할 수 있지만, 로컬 클래스는 메서드 내에서만 사용된다. 멤버 클래스와 로컬 클래스가 정의되고 컴파일되면 실제 파일도 별도로 생성된다.

 

멤버 클래스의 파일명은 아래와 같다.

바깥클래스명 $내부클래스명.class

로컬 클래스의 파일명은 아래와 같다.

바깥클래스명$1내부클래스명.class

 

멤버 클래스

멤버 클래스는 static 멤버 클래스와 인스턴스 멤버 클래스로 나눠진다. static 멤버 클래스(static inner class)는 내부 클래스의 객체를 바깥 클래스에 대해 독립적으로 생성할 때 사용된다. static 키워드를 가진 내부클래스로, 멤버변수나 메서드처럼 클래스 내부에서 선언된다. 내부 클래스 내에 static 멤버가 있으면 반드시 static 내부 클래스로 선언해야 한다.

public class Outer {
    // Outer 클래스의 내용
    ...
    public static class Inner {
        // Inner 클래스의 내용
    }
}

다른 곳에서 Inner 클래스 객체를 생성하기 위해 Inner 클래스에 접근하려면, 아래와 같이 객체를 생성한다.

Outer.inner inn = new Outer.Inner();

 

인스턴스 내부 클래스

인스턴스 내부 클래스는 static 내부 클래스와 같은 위치에 선언하지만, static 키워드가 포함되지 않는다.

public class Outer {
    // Outer 클래스의 내용
    ...
    public class Inner {
        // Inner 클래스의 내용
    }
}

다른 곳에서 안쪽 클래스의 객체를 생성하기 위해서는 바깥 클래스의 객체를 먼저 생성하고, 그 객체변수를 이용해서 내부 클래스의 객체를 생성한다.

Outer outer = new Outer();
Outer.Inner inn = outer.new Inner();

 

로컬 클래스

static 내부 클래스나 인스턴스 내부 클래스는 바깥 클래스의 멤버와 같은 위치에 선언했으나, 로컬 클래스는 바깥 클래스의 메서드 내에 선언된다.

package chapter10;

public class OuterEx {
	public static void main(String[] args) {
		Outer outer = new Outer();
		Outer.SInner sInner = new Outer.SInner();
		Outer.Inner inner = new Outer().new Inner();
		Outer.Inner inner2 = outer.new Inner();
		
		System.out.println(Outer.SInner.si3);
		System.out.println(sInner.i3);
		
		System.out.println(inner.i2);
		System.out.println(Outer.Inner.si2);
		
	}
}

class Outer {
	// 인스턴스 변수 : 인스턴스가 필요
	// 클래스 변수 : 인스턴스가 안필요함
	// 클래스 변수를 만들면 inner, Sinner 접근 가능
	// 인스턴스 변수를 만들면 inner 접근 가능, sinner 접근 불가능
	// iv
	int i;
	// cv
	static int si;
	
	class Inner {
		int i2;
		static int si2;  
		{
			i = 10;
			si = 20;
		}
	} // 인스턴스 변수가 필요함
	
	static class SInner {
		int i3;
		static int si3;
		{
//			i = 30;  // 에러생성
			si = 40;
		}
	} // 인스턴스 변수가 안 필요함
}
package chapter10;

import java.util.HashMap;
import java.util.Map;
//import java.util.Map.Entry;

public class OuterEx {
	public static void main(String[] args) {
		Outer outer = new Outer();
		Outer.SInner sInner = new Outer.SInner();
		Outer.Inner inner = new Outer().new Inner();
		Outer.Inner inner2 = outer.new Inner();
		
		System.out.println(Outer.SInner.si3);
		System.out.println(sInner.i3);
		
		System.out.println(inner.i2);
		System.out.println(Outer.Inner.si2);

		Map<String, Integer> map = new HashMap<>();
		map.put("A", 10);
		map.put("B", 20);
		System.out.println(map);
		System.out.println(map.get("B"));
		
//		for(Entry<K, V> : map) {
		for(Map.Entry<String, Integer> e : map.entrySet()) {  // 각각의 따로 값들을 확인 가능
			System.out.println(e.getKey());
			System.out.println(e.getValue());
		}
		
	}
}

class Outer {
	// 인스턴스 변수 : 인스턴스가 필요
	// 클래스 변수 : 인스턴스가 안필요함
	// 클래스 변수를 만들면 inner, Sinner 접근 가능
	// 인스턴스 변수를 만들면 inner 접근 가능, sinner 접근 불가능
	// iv
	int i;
	// cv
	static int si;
	
	class Inner {
		int i2;
		static int si2;  
		{
			i = 10;
			si = 20;
		}
	} // 인스턴스 변수가 필요함
	
	static class SInner {
		int i3;
		static int si3;
		{
//			i = 30;  // 에러생성
			si = 40;
		}
	} // 인스턴스 변수가 안 필요함
}

10.2 내부 인터페이스

내부 인터페이스는 클래스의 멤버로 선언된 인터페이스이다. 이 내부 인터페이스를 사용하는 이유도 속해 있는 바깥 클래스와 직접적인 관련이 있는 경우이다. (안드로이드의 이벤트 처리 인터페이스가 이런 형태로 만들어져 있는 경우가 많음)

class 클래스명 {
    interface 인터페이스명 {
        void method(); // 추상메서드
    }
}

 

package chapter10;

public class LocalEx {
	public static void main(String[] args) {
		Fightable f1 = getFighter();
		Fightable f2 = new Fighter();
		Fightable f3 = getFighter2();
		Fightable f4 = new Fightable() {  // 블록안에만 익명클래스 (1)일지 (2)일지는 모름
			
			@Override
			public void fight() {  
				// TODO Auto-generated method stub
				System.out.println("f4.fight()");
			}
		};		
		
		f1.fight();
		f2.fight();
		f3.fight();
		f4.fight();

		
	}
	// 지역 클래스
	static Fightable getFighter() {
		class MyFighter implements Fightable {
			public void fight() {
				System.out.println("MyFighter.fight()");
			}
		}
		return new MyFighter();
	}
	// 익명 클래스
	static Fightable getFighter2() {
		return new Fightable() {
			public void fight() {
				System.out.println("getFighter2().fight()");
			}
		};
	}
	
	
}

interface Fightable {
	void fight();
}

class Fighter implements Fightable {

	@Override
	public void fight() {
		// TODO Auto-generated method stub
		System.out.println("Fighter.fight()");
	}
	
	
}

 

728x90
300x250