티스토리 뷰
9.1 중첩 클래스
- 중첩 클래스: 클래스 내부에 선언한 클래스
- 멤버 클래스: 클래스의 멤버로서 선언되는 중첩 클래스
- 로컬 클래스: 메소드 내부 선언되는 중첩 클래스
- 특정 클래스만 관계를 맺을 경우에는 중첩 클래스로 선언하는 것이 유지보수에 도움이 된다.
- 클래스의 멤버를 쉽게 사용할 수 있음
- 코드의 복잡성을 줄일 수 있음
- 컴파일하면 바이트코드 파일이 생성
9.2 인스턴스 멤버 클래스
- 바깥 클래스에서만 사용되기 때문에 내부 클래스는 주로 private접근 제한을 갖는 것이 일반적
- 바깥 클래스 어디에서나 생성할 수는 없고 인스턴스 필드값, 생성자, 인스턴스 메소드에서 생성할 수 있음
- 왜냐면 바깥 클래스 객체가 있어야 내부 클래스 객체도 생성할 수 있기 때문이다
- 내부 클래스를 바깥 클래스 외부에 생성하기 위해서는 바깥 클래스를 먼저 생성한 다음 내부 클래스의 객체를 생성해야 한다.
public class InstanceClassDemo {
public static void main(String[] args) {
InsideClass insideClass = new InsideClass();
// 바깥 클래스 객체 생성 후 내부 클래스 객체 생성
InsideClass.OusideClass ousideClass = insideClass.new OusideClass();
}
}
class InsideClass {
// 내부 클래스
class OusideClass {
int field = 1; // 필드
OusideClass() {} // 생성자
void method1() {} // 메소드
// Java 17부터는 정적 필드, 정적 멧드 사용 가능
}
// 인스턴스 필드값으로 생성
OusideClass ousideClass = new OusideClass();
// 생성자 안에서 생성
InsideClass(){
OusideClass ousideClass = new OusideClass();
}
// 메소드 안에서 생성
void method(){
OusideClass ousideClass = new OusideClass();
}
}
9.3 정적 멤버 클래스
- 내부 클래스는 바깥 클래스 외부에서도 사용되기 때문에 public, (default) 접근 제한을 갖는 것이 일반적
- 내부 클래스는 바깥 클래스 어디에서든 생성할 수 있음
- 내부 클래스를 외부에서 사용하기 위해서 바깥 클래스 객체는 생성하지 않아도 된다.
public class StaticClassDemo {
public static void main(String[] args) {
// 바깥 클래스 객체 없이 바로 접근해서 생성 가능
InsideClass2.OusideClass2 ousideClass2 = new InsideClass2.OusideClass2();
InsideClass2.OusideClass2.field = 2;
}
}
class InsideClass2 {
// 정적 멤버 클래스
static class OusideClass2 {
static int field = 1; // 필드
OusideClass2() {} // 생성자
void method1() {} // 메소드
// Java 17부터는 정적 필드, 정적 멧드 사용 가능
}
// 인스턴스 필드값으로 생성
OusideClass2 ousideClass = new OusideClass2();
// 정적 필드값으로 생성
static OusideClass2 outsideClass2 = new OusideClass2();
// 생성자 안에서 생성
InsideClass2(){
OusideClass2 ousideClass = new OusideClass2();
}
// 메소드 안에서 생성
void method() {
OusideClass2 ousideClass = new OusideClass2();
}
// 정적 메소드 안에서 생성
static void method2() {
OusideClass2 ousideClass = new OusideClass2();
}
}
9.4 로컬 클래스
- 생성자 또는 메소드 내부에 생성된 클래스
- 생성자와 메소드가 실행될 동안에만 객체를 생성할 수 있음
- 로컬 변수를 로컬 클래스에서 사용할 경우, 로컬 변수는 final 특성을 갖게 되어 읽을 수만 있고 수정은 불가
class A {
A() {
class B {
int field = 0;
B() {}
void bMethod() { }
}
B b = new B();
b.bMethod();
}
void method() {
int var = 1;
class C {
// var = 2; 변경 불가
}
}
}
9.5 바깥 멤버 접근
내부 클래스는 바깥 클래스의 멤버에 접근할 수 있음
- 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드와 메소드, 정적 필드와 메소드 모두 사용 가능
- 정적 멤버 클래스는 바깥 객체가 없어도 사용 가능해야 함로 바깥 클래스의 정적 필드와 메소드만 사용 가능
바깥 클래스의 객체 접근
public class ADemo {
public static void main(String[] args) {
A2 a2 = new A2();
a2.useB2();
}
}
class A2 {
String field = "A2";
class B2 {
String field = "B2";
void print() {
// 내부 클래스의 필드 사용할 때
System.out.println(this.field);
// 바깥 클래스의 필드 사용할 때
System.out.println(A2.this.field);
}
}
void useB2() {
B2 b2 = new B2();
b2.print();
}
}
9.6 중첩 인터페이스
- 클래스의 멤버로 선언된 인터페이스
- 인터페이스를 클래스 내부에 선언하는 이유는 해당 클래스와 긴밀한 관계를 맺는 구현 객체를 만들기 위해서
- 중첩 인터페이스는 암시적으로 static
- 안드로이드와 같은 UI프로그램에서 이벤트를 처리할 목적으로 많이 활용됨
public class ButtonDemo {
public static void main(String[] args) {
Button okbutton = new Button();
// Ok버튼이 클릭되었을 때 실행될 구현부를 작성
class OKListener implements Button.ClickListener {
@Override
public void onClikc() {
System.out.println("OK버튼 클릭");
}
}
// 구현 객체 주입
okbutton.setClickListener(new OKListener());
// 버튼 누르기
okbutton.press();
}
}
class Button {
interface ClickListener {
void onClikc();
}
// 외부에서 settter를 통해 ClickListener 구현 객체를 필드에 저장할 수 있도록 함
private ClickListener clickListener;
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
// button이 클릭되어쓸 때 실행되는 메소드 선언
public void press(){
clickListener.onClikc();
}
}
9.7 익명 객체
- 이름이 없는 객체
- 명시적으로 클래스를 선언하지 않기 때문에 쉽게 객체를 생성할 수 있음
- 필드값, 로컬 변수값, 매개변수값으로 주로 사요
익명 자식 객체 = 클래스를 상속해서 만들 경우
public class CarDemo {
public static void main(String[] args) {
Car car = new Car();
car.run1();
car.run2();
car.run3();
car.run4(new Tire(){
@Override
void roll() {
System.out.println("익명 자식 객체 매개값으로 타이어가 굴러갑니다.");
}
});
}
}
class Car {
Tire tire1 = new Tire();
void run1() {
tire1.roll();
}
// 필드값으로 사용
Tire tire2 = new Tire() {
@Override
void roll() {
System.out.println("익명 자식 객체 필드값 타이어가 굴러갑니다");
}
};
void run2() {
tire2.roll();
}
// 로컬 변수값으로 사용
void run3() {
Tire tire = new Tire() {
@Override
void roll() {
System.out.println("익명 자식 객체 로컬 변수 값 타이어가 굴러갑니다");
}
};
tire.roll();
}
// 매개변수값으로 사용
void run4(Tire tire) {
tire.roll();
}
}
class Tire {
void roll(){
System.out.println("타이어가 굴러갑니다");
}
}
익명 구현 객체 = 인터페이스를 구현해서 만들 경우
(익명 자식 객체 참고, 클래스가 인터페이스가 되었을 뿐 흡사함)
'도서 및 강의 > 이것이 자바다' 카테고리의 다른 글
이것이 자바다 3판 챕터 11 (0) | 2024.09.18 |
---|---|
이것이 자바다 3판 챕터 10 (1) | 2024.09.18 |
이것이 자바다 3판 챕터 8 (2) | 2024.09.17 |
이것이 자바다 3판 챕터 7 (0) | 2024.09.17 |
이것이 자바다 3판 챕터 6 (0) | 2024.08.26 |
최근에 올라온 글