[Java] Java의 정석 정리 (내부/익명 클래스)

송병훈·2022년 10월 4일
0

자바의 정석

목록 보기
14/15
post-thumbnail

내부 클래스 (inner class)

내부클래스의 장점

  • 내부클래스에서 외부클래스의 멤버들에 쉽게 접근할 수 있다.
    -> private까지도 가능
  • 코드의 복잡성을 줄일 수 있다.(캡슐화)
    -> 내부클래스를 외부클래스에서만 사용한다면 넣어라
  • 멤버들 간의 접근이 용이해진다.
    -> 내부클래스가 외부클래스의 멤버를 전역변수처럼 바로 사용함. (객체생성x)
  • 내부클래스의 접근제어자는 변수처럼 protected와 private까지도 가능하다.

내부클래스 특징

1. 멤버변수와 사용법이 같다.

내부클래스의 특징은 iv, cv, lv 처럼 쓰인다는 것이다.
인스턴스 클래스, 스태틱 클래스, 지역 클래스, + 익명클래스
(지역클래스: 메소드 안의 클래스 -> 다른 곳에서는 사용 못함)
(익명클래스: 클래스의 선언과 객체생성을 동시에 하는 이름없는 클래스)

static 멤버가 인스턴스멤버를 사용할 수 없듯이
static 클래스가 인스턴스 클래스 및 인스턴스 멤버를 사용할 수 없다.

class InnerEx1 { 
      class InstanceInner { 
            int iv = 100; 
//          static int cv = 100;            // 에러! static변수를 선언할 수 없다. 
            final static int CONST = 100;   // final static은 상수이므로 허용한다. 
      } 

      static class StaticInner { 
            int iv = 200; 
            static int cv = 200;       // static클래스만 static멤버를 정의할 수 있다. 
      } 

      void myMethod() { 
            class LocalInner { 
                  int iv = 300; 
//                static int cv = 300;          // 에러! static변수를 선언할 수 없다. 
                  final static int CONST = 300; // final static은 상수이므로 허용 
            } 
      } 

      public static void main(String args[]) { 
            System.out.println(InstanceInner.CONST); 
            System.out.println(StaticInner.cv); 
      } 
} 

2. 내부클래스 객체 생성

class Outer {
	class InstanceInner {
		int iv=100;
	}
	static class StaticInner {
		int iv=200;
		static int cv=300;
	}

	void myMethod() {
		class LocalInner {
			int iv=400;
		}
	}
}

class InnerEx4 {
	public static void main(String[] args) {
		// 인스턴스클래스의 인스턴스를 생성하려면
		// 외부 클래스의 인스턴스를 먼저 생성해야 한다.
		Outer oc = new Outer();
		Outer.InstanceInner ii = oc.new InstanceInner();

		System.out.println("ii.iv : "+ ii.iv);
		System.out.println("Outer.StaticInner.cv : " + Outer.StaticInner.cv);

	     // 스태틱 내부 클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
		Outer.StaticInner si = new Outer.StaticInner();	// [외부클래스명].[내부클래스명]
		System.out.println("si.iv : "+ si.iv);
	}
}

3. 내부클래스 멤버 접근

같은 이름의 변수가 있을 때 접근방법

class Outer {
	int value=10;	// Outer.this.value				

	class Inner {
		int value=20;	// this.value

		void method1() {
			int value=30;
			System.out.println("           value :" + value);		// 지역변수
			System.out.println("      this.value :" + this.value);	// 내부클래스의 전역변수
			System.out.println("Outer.this.value :" + Outer.this.value);	// 외부클래스의 전역변수 
            // [외부클래스명].this.[변수명]
		}
	} // Inner클래스의 끝
} // Outer클래스의 끝

class InnerEx5 {
	public static void main(String args[]) {
		Outer outer = new Outer();
		Outer.Inner inner = outer.new Inner();
		inner.method1();
	}
} // InnerEx5 끝

익명클래스 (anonymous class)

이름이 없는 일회용 클래스.
선언과 객체 생성을 동시에 함.
하나의 객체만 생성 가능함.

new 조상클래스명() {
	// 멤버 선언
}

또는

new 구현할인터페이스명() {
	// 멤버 선언
}

예시)

import java.awt.*;
import java.awt.event.*;

class  InnerEx7{
	public static void main(String[] args) {
		Button b = new Button("Start");
		b.addActionListener(new EventHandler());	// EventHandler 클래스 선언
	}
}
	
class EventHandler implements ActionListener {	// EventHandler 클래스 코드
	public void actionPerformed(ActionEvent e) {
		System.out.println("ActionEvent occurred!!!");
	}
}

여기서 EventHandler 클래스를 익명클래스로 만드는 방법은

  1. 매개변수에 위치한 new EventHandler()
    구현할 인터페이스명인 new ActionListener() 로 바꾼다.

  2. EventHandler 의 구현부를 그대로 이어붙인다.

import java.awt.*;
import java.awt.event.*;

class  InnerEx8 {
	public static void main(String[] args) {
		Button b = new Button("Start");
		b.addActionListener(new ActionListener() {	// 이름 바꾸고, 구현부 넣음
                                    public void actionPerformed(ActionEvent e) {
                                   		System.out.println("ActionEvent occurred!!!");
                                	} // 구현부 내부 메소드의 끝
                            } // 익명 클래스 구현부 끝
		);	// addActionListener 메소드의 끝
	} // main메서드의 끝
} // InnerEx8클래스의 끝

오늘의 내용은 여기까지입니다.
생각보다 별거 없죠?ㅎㅎ

profile
성실하고 꼼꼼하게

0개의 댓글