남궁성님의 Java의 정석(3rd Edition)을 보고 정리한 글입니다.
내부 클래스(inner class)?
- 두 클래스간의 긴밀한 관계를 가지며, 두 클래스의 멤버들 간에 서로 쉽게 접근할 수 있다.
- 내부 클래스의 종류에는 인스턴스 클래스, static 클래스, Local 클래스, 익명 클래스가 있다.
- 내부 클래스도 클래스이므로 abstract나 final과 같은 제어자를 사용할 수 있다.
- 내부 클래스도 멤버변수처럼 접근제어자도 사용할 수 있다.
a. 인스턴스(instance) 클래스?
- 외부 클래스의 멤버변수 선언 위치에 선언
- 인스턴스 멤버처럼 사용
- 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업
- 접근제어자도 인스턴스 멤버처럼 동일하게 적용된다.
class Cart { // 장바구니 클래스
ArrayList<Item> list = new ArrayList<Item>();
void addItem(String name, int num, int unitPrice) {
list.add(new Item(name, num, unitPrice));
}
void removeItem(int index) {
list.remove(index);
}
int getItemNum() {
return list.size();
}
Item getItem(int index) {
return list.get(index);
}
int getTotalPrice() {
int total = 0;
for (Item item : list)
total += item.getPrice();
return total;
}
void chnageItemNumber(int index, int num) {
Item item = list.get(index);
item.num = num;
}
class Item { // 상품 항목 클래스 => Cart 클래스에 종속된 클래스(이너클래스)
String name;
int num;
int unitPrice;
Item(String name, int num, int unitPrice) {
this.name = name;
this.num = num;
this.unitPrice = unitPrice;
}
int getPrice() {
return num * unitPrice;
}
}
}
public class NestedClassExample1 {
public static void main(String args[]) {
Cart cart = new Cart();
cart.addItem("쵸콜렛", 3, 1000);
cart.addItem("케이크", 1, 25000);
cart.addItem("샴페인", 1, 7000);
Cart.Item item = cart.new Item("꽃다발", 1, 50000); // 내부 클래스 사용
cart.list.add(item);
printCart(cart);
}
static void printCart(Cart cart) {
int num = cart.getItemNum();
System.out.println(" 상품명 수량 단가 금액");
System.out.println("----------------------------------");
for (int cnt = 0; cnt < num; cnt++) {
Cart.Item item = cart.getItem(cnt);
System.out.printf("%3d %5s %5d %7d %7d %n", cnt + 1, item.name, item.num, item.unitPrice, item.getPrice());
}
System.out.println("----------------------------------");
System.out.printf(" 총계 %10d %n", cart.getTotalPrice());
}
}
실행결과
상품명 수량 단가 금액
----------------------------------
1 쵸콜렛 3 1000 3000
2 케이크 1 25000 25000
3 샴페인 1 7000 7000
4 꽃다발 1 50000 50000
----------------------------------
총계 85000
b. 스태틱(static) 클래스?
- 외부 클래스의 멤버변수 선언 위치에 선언
- static 멤버처럼 다루어진다.
- 주로 외부 클래스의 static 멤버(메서드)에 사용
- 접근제어자도 static 멤버처럼 동일하게 적용
public class Outer {
static int cnt = 0;
static class StaicInner1 {
void up() {
cnt++;
}
int getCnt() {
return cnt;
}
}
static class StaicInner2 {
void up() {
cnt++;
}
int getCnt() {
return cnt;
}
}
}
public static void main(String[] args) {
Outer.StaicInner1 si1 = new Outer.StaicInner1();
Outer.StaicInner2 si2 = new Outer.StaicInner2();
si1.up();
System.out.println(si2.getCnt());
si2.up();
System.out.println(si1.getCnt());
}
실행결과
1
2
c. 로컬(local) 클래스?
- 외부 클래스의 메서드나 초기화블럭안에 선언
- 선언된 영역 내부에서만 사용
- local 클래스가 포함된 메서드에 정의된 지역변수도 사용할 수 있다.(읽기만 가능) ⇒ 인스턴스 소멸 시점에 참조하는 것을 방지
public class NestedClassExample7 {
public static void main(String args[]) {
int a = 10;
class ContactInfo { // local 클래스(main 메서드 내에서만 사용 가능)
String address;
String phoneNo;
a = 15; // 에러
int b = a; // 정상 동작
ContactInfo(String address, String phoneNo) {
this.address = address;
this.phoneNo = phoneNo;
}
}
HashMap<String, ContactInfo> hashtable = new HashMap<String, ContactInfo>();
hashtable.put("이순희", new ContactInfo("서울시 강남구", "02-547-0000"));
hashtable.put("한지영", new ContactInfo("서울시 성북구", "02-920-0000"));
hashtable.put("박철규", new ContactInfo("경기도 고양시", "031-915-0000"));
ContactInfo obj = hashtable.get("한지영");
System.out.println("<한지영의 연락처>");
System.out.println("주소:" + obj.address);
System.out.println("전화번호:" + obj.phoneNo);
}
}
실행결과
<한지영의 연락처>
주소:서울시 성북구
전화번호:02-920-0000
d. 익명(anoymous) 클래스?
- 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)
- new int[] {1, 2, 3} ⇒ 이런것도 익명 클래스
public interface Message {
void send();
}
public class EmailSend implements Message {
@Override
public void send() {
System.out.println("외부 클래스 에서 보내는 이메일");
}
//anonymousSend 메서드 안에 익명 클래스를 사용
public Message anonymousSend() {
return new Message() { // 익명 클래스
@Override
public void send() {
System.out.println("익명 클래스 에서 보내는 이메일");
}
};
}
}
public class InnerExam {
public static void main(String[] args) {
EmailSend emailSend = new EmailSend();
emailSend.send();
Message message = emailSend.anonymousSend();
message.send();
}
}
'Programming > Java' 카테고리의 다른 글
[Java] .java(소스파일) vs. .class(바이트코드파일) vs. .jar (0) | 2023.10.20 |
---|---|
[Java] try-catch 예외처리 (0) | 2023.10.16 |
[Java] 다형성 (추상클래스 - 인터페이스) (0) | 2023.10.16 |
[Java] 자바의 제어자 정리 (0) | 2023.10.16 |
[Java] package와 import (0) | 2023.10.16 |