햄발
Inner class 본문
Inner class
자바에서 내부 클래스(Inner Class) 는 한 클래스 내부에 선언된 클래스를 말한다. 내부 클래스를 선언하게 되면 내부 클래스와 외부 클래스라고 표현할 수 있다. 내부 클래스는 보통 외부 클래스와 연관이 있는 경우가 많고 다른 곳에서 거의 사용할 일이 없는 경우에 내부 클래스를 선언해서 활용을 한다.
코드예시
class OuterClass {
private int num = 10;
class InnerClass {
public void display() {
System.out.println("num: " + num);
}
}
}
public class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display(); // 출력: num: 10
}
}
Inner class 의 종류
멤버 내부 클래스(Member Inner Class)
외부 클래스의 필드와 같은 위치에 선언되며, 외부 클래스의 인스턴스에 종속적이다. 멤버 내부 클래스의 인스턴스는 외부 클래스의 인스턴스가 있어야 생성할 수 있다.
정적 내부 클래스(Static Inner Class)
외부 클래스의 필드에 선언되지만, static 키워드를 사용하여 선언된다. 정적 내부 클래스는 외부 클래스의 인스턴스와 독립적으로 존재할 수 있으며, 주로 관련 있는 클래스들을 논리적으로 그룹화할 때 사용된다.
지역 내부 클래스(Local Inner Class)
메서드 내부에 선언되며, 선언된 메서드 내에서만 사용된다. 지역 내부 클래스는 해당 메서드의 지역 변수와 마찬가지로 스코프가 제한된다.
익명 내부 클래스(Anonymous Inner Class)
이름이 없는 내부 클래스로, 주로 인터페이스나 추상 클래스를 간편하게 구현할 때 사용된다. 익명 내부 클래스는 오직 하나의 인스턴스만 생성할 수 있으며, 주로 이벤트 처리나 콜백 구현에 사용된다.
멤버 내부 클래스
코드예시
package useful.ch07;
class Book {
private String title;
private Author author;
// 생성자에서 책의 제목과 저자의 정보를 초기화
public Book(String title, String authorName, String authorEmail) {
this.title = title;
this.author = new Author(authorName, authorEmail);
}
public void printBookDetails() {
System.out.println("Book Title: " + title);
System.out.println("작가 이름 : " + author.name + ", 이메일 : " + author.email);
}
// 멤버 내부 클래스
class Author {
private String name;
private String email;
// 생성자에서 저자의 이름과 이메일을 초기화
public Author(String name, String email) {
this.name = name;
this.email = email;
}
}
}
package useful.ex06;
public class BookTest {
public static void main(String[] args) {
// 멤버 내부 클래스를 사용하는 설계 방식의 주요 이점
// 캡슐화를 강화
// - 내부적으로 어떤 기능이 있는지 숨길 수 있다
// 로직의 응집도 향상
// - 특정 기능이나 데이터를 사용하는 코드를 한 곳에 모으면,
// 코드의 응집도가 향상됩니다.
// 이는 코드를 이해하고 유지보수하기 쉽게 만들어 줍니다.
Book book = new Book("홍길동전", "허균", "허균@example.com");
book.printBookDetails();
// 외부에서 Book 안에 있는 내부클래스 Author에 쉽게 접근이 안됨
}
}
정적 내부 클래스(Static Inner Class)
코드예시
package useful.ch07;
public class Spaceship {
// 배열 - 이 우주선 설계는 엔진을 최대 3개 까지
// 장착할 수 있다.
private Engine innerEngine;
// 정적 내부 클래스 Engine
public static class Engine {
public static int engineCount = 0;
private int serialNumber;
public Engine() {
this.serialNumber = ++engineCount;
}
public void start() {
System.out.println("Engine " + serialNumber + " 동작 합니다. 부릉~~");
}
} // end of inner class
// 우주선에 엔진 추가
public void addEngine(Engine engine) {
innerEngine = engine;
System.out.println("엔진 : " + innerEngine.serialNumber + " 을 장착 합니다");
Engine.engineCount++;
}
public void startSpaceShip() {
if (innerEngine == null) {
System.out.println("엔진을 먼저 장착해주세요");
} else {
System.out.println("달나라로 출발 합니다 슈웅~");
}
}
} // end of class
package useful.ch07;
import useful.ch07.Spaceship.Engine;
public class SpaceshipTest {
public static void main(String[] args) {
Spaceship spaceship = new Spaceship();
spaceship.startSpaceShip();
// 외부에서 엔진을 만들어서
// spaceship 주입 시켜야 한다
Engine 누리호1번엔진 = new Engine();
Engine 누리호2번엔진 = new Spaceship.Engine();
Engine 누리호3번엔진 = new Spaceship.Engine();
// 변수명은 한글로 작성하지 말자 !!
System.out.println("--------------");
spaceship.addEngine(누리호3번엔진);
spaceship.startSpaceShip();
// 사용하는 이유
// [논리적인 그룹화]
// 정적 내부 클래스는 외부 클래스와 논리적으로
// 관련 있는 클래스들을 그룹화 하는데 유용하다.
}
}
지역 내부 클래스(Local Inner Class)
코드예시
public class OuterClass {
// 외부 클래스의 메서드
public void display() {
// 지역 내부 클래스
class LocalInnerClass {
void printMessage() {
System.out.println("Hello from the Local Inner Class!");
}
}
// 지역 내부 클래스의 인스턴스 생성
LocalInnerClass inner = new LocalInnerClass();
// 메서드 호출
inner.printMessage();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}
지역 내부 클래스는 특정 메서드 내에서만 정의되고 사용되는 클래스로, 메서드 실행 시에만 존재하고 메서드의 지역 변수처럼 동작한다. 이 클래스는 외부에서는 접근할 수 없으며, 주로 메서드 내에서 일회성 작업을 수행하는 객체를 생성할 때 유용하다.
익명 내부 클래스
코드예시
package useful.ch07;
/**
* 익명 내부클래스에 대해서 살펴 보자.
*/
public class Outter {
Runnable runable1; // 인터페이스 이다.
// 인터페이스는 기본적으로 객체를 만들 수 없다
// 하지면 익명 내부 클래스로 구현할 수 있다.
// 이런것들을 앞으로 우리는 구현 클래스라 부르자
public Outter() {
// Runnable 인터페이스를 구현 클래스로 만들었다.
// Outter 클래스 내부에 있고, 이녀석을 만들었지만
// 다른곳에서 부를 방법이 없다. 이름이 없음 - 익명
// 종합 하면 익명 내부 클래스 명칭 한다.
new Runnable() {
public void run() {
// ...
}
};
}
// 변수에 Runnable 구현 클래스 대입
Runnable runner = new Runnable() {
@Override
public void run() {
System.out.println("Runnable 이 구현된 익명 클래스 변수");
}
};
// 리턴 타입으로 Runnable 구현 클래스 반환
Runnable getRunnable(int i) {
int num = 100;
return new Runnable() {
@Override
public void run() {
// num = 200; //에러 남
// i = 10; //에러 남
System.out.println(i);
System.out.println(num);
}
};
}
}
'Java' 카테고리의 다른 글
Java 표준 입출력 (0) | 2024.05.23 |
---|---|
Java I/O (0) | 2024.05.23 |
LinkedList (0) | 2024.05.22 |
Queue (1) | 2024.05.21 |
배열 활용 (5) | 2024.05.03 |