내부클래스
- 클래스 내에 선언된 클래스이다.
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근이 가능.
- 복잡성을 줄임.(캡슐화)
내부클래스의 종류
- 멤버 클래스
- 지역 클래스
- static 클래스
- 익명 클래스
각각의 클래스의 구조는 아래와 같다.
public class Outer { class MemberInner {} // 멤버 클래스 static class StaticInner {} // static 클래스 void myMethod() { class LocalInner {} // 지역 클래스 } } | cs |
멤버클래스
class Outer { ... class Inner { } ... } | cs |
- 객체를 생성해야만 사용할 수 있는 멤버들과 같은 위치에 정의되는 클래스.
public class MemberInnerClass { // 내부클래스 정의 public class Inner { public void call() { System.out.println("호출"); } } public static void main(String[] args) { // 호출 1 // MemberInnerClass mic = new MemberInnerClass(); // Inner inner = mic.new Inner(); // 호출 2 MemberInnerClass.Inner inner = new MemberInnerClass().new Inner(); inner.call(); } } | cs |
- 보통 메인에서는 외부 클래스를 생성하고 외부 멤버메소드에서 내부 클래스를 호출한다.
Static클래스
public class StaticClass { int i; static int j; public void instanceOutMethod() { System.out.println("instanceOutMethod"); } public static void staticOutMethod() { System.out.println("staticOutMethod"); } static class Static{ static String name; public static void staticInMethod(){ System.out.println("안쪽 메서드"); StaticClass.j = 100; StaticClass.staticOutMethod(); // Static 메소드에서는 Instance 메소드를 사용 할 수 없다. // instanceOutMethod(); } } public static void main(String[] args) { // Static의 멤버 사용 Static.name = "Static"; Static.staticInMethod(); } } | cs |
- 내부클래스에 static을 붙여 정의.
- static 클래스는 객체화 하지 않고 사용
지역클래스
public class LocalClass { int outer_i; public void myMethod(int i, final int j){ final int local_i = 0; // int local_j = 0; class Local { int k; public void localMethod() { System.out.println("바깥클래스의 인스턴스변수" + outer_i); // final이 붙어있지 않는 파라미터는 사용할 수 없다. // System.out.println("파라메터 j =" + i); System.out.println("파라메터 j =" + j); // final이 붙어있지 않는 변수는 지역변수에서 사용할 수 없다. System.out.println("지역변수 local_i =" + local_i); System.out.println("지역클래스의 메소드"); } } Local local = new Local(); local.k = 10; local.localMethod(); } public static void main(String[] args) { LocalClass tl = new LocalClass(); tl.myMethod(100, 200); } } | cs |
- 메소드 안에 클래스를 정의.
- 메소드 내부에만 지역변수처럼 클래스를 사용할 때
- 지역변수, 파라미터에 final을 붙여야 사용할 수 있다.
- 메소드 외부에서 사용할 수 없다.
익명클래스
- 이름이 없는 일회용 클래스
- 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있다.
- 예제1
public class AnonymousBean1 { private String msg = "익명클래스1"; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } | cs |
public class Anonymous1 { // 생성자 public Anonymous1() { print(new AnonymousBean1()); print(new AnonymousBean1() { // AnonymousBean1()을 상속받고 재정의 한다. // 즉, AnonymousBean1()를 상속받은 익명의 자식클래스다. String msg = "익명클래스2"; public String getMsg() { return msg; } }); } public void print(AnonymousBean1 m) { String msg = m.getMsg(); // AnonymousBean1 클래스의 msg 를 리턴한다. System.out.println("msg:" + msg); } public static void main(String[] args) { new Anonymous1(); // 생성자만 필요하므로 인스턴스를 저장하지 않아도 된다. } } | cs |
- 예제2
public interface AnonymousBean2 { public void stop(); } | cs |
public class AnonymousBean3 { public void go() { System.out.println("AnonymousBean3에 있는 go메소드"); } } | cs |
public class Anonymous2 { // AnonymousBean2 인터페이스를 구현 AnonymousBean2 in_interface = new AnonymousBean2() { @Override public void stop() { System.out.println("익명 내부클래스"); } }; // AnonymousBean3 클래스를 상속받아 재정의 AnonymousBean3 in_class = new AnonymousBean3() { @Override public void go() { System.out.println("AnonymousBean3에서 재정의한 go 메소드"); } }; public static void main(String[] args) { Anonymous2 in = new Anonymous2(); in.in_interface.stop(); // 익명내부클래스의 메소드 호출 -> 인터페이스 in.in_class.go(); // 익명내부클래스의 메소드 호출 -> 클래스 } } | cs |