// 인스턴스 맴버 클래스
class A {
class B {...} // A객체를 생성해야 B객체 생성 가능
}
// 정적 맴버 클래스
class A {
static class B {...} // A객체를 생성하지 않아도 B객체 생성 가능
}
바이트코드 파일
A$B.class
class A {
void method() { // method가 실행할 때만 B객체 생성 가능
class B {...}
}
}
바이트코드 파일
A$1B.class
[public] class A {
[public | private] class B {...}
}
| 구분 | 접근범위 |
|---|---|
| public class B | 다른 패키지에서 B클래스 사용 가능 |
| (default) class B | 같은 패키지에서만 B클래스 사용 가능 |
| private class B | A 클래스 내에서만 B 클래스 사용 가능 |
public class A {
// 인스턴스 맴버 클래스
class B {
public void methodB(){...}
}
// 인스턴스 필드 값으로 B객체 대입
B field = new B();
// 생성자
A() {
B b = new B();
}
}
// 클래스 B 객체 사용
public class AExample {
public static void main(String[] args) {
A a = new A(); // A 클래스 객체 생성
A.B b = a.new B(); // A 객체 안의 B 클래스 객체 생성
b.methodB(); // B 객체의 메소드 실행
}
}
[public] class A {
[public | private] static class B {...}
}
| 구분 | 접근범위 |
|---|---|
| public static class B | 다른 패키지에서 B클래스 사용 가능 |
| (default) static class B | 같은 패키지에서만 B클래스 사용 가능 |
| private static class B | A 클래스 내에서만 B 클래스 사용 가능 |
public class A {
// 인스턴스 맴버 클래스
static class B {
public void methodB(){...}
}
// 인스턴스 필드 값으로 B객체 대입
B field1 = new B();
// 정적 필드 값으로 B객체 대입
static B field2 = new B();
// 생성자
A() {
B b = new B();
}
// 인스턴스 메소드
void method1() {
B b = new B();
}
static void method2() {
B b = new B();
}
}
// 클래스 B 객체 사용
public class AExample {
public static void main(String[] args) {
A.B b = new A.B(); // B 객체 생성
// (A 객체를 생성하지 않아도 B 클래스 사용가능)
b.methodB(); // B 객체의 메소드 실행
}
}
로컬 클래스의 예시
public class A {
//생성자 안에 클래스 B 선언
public A() {
class B {...} // 접근 제한자 불가능 (외부 접근 x)
//객체 생성
B b = new B();
} // A() 생성자 외부에서 클래스 C 사용불가
//메소드 안에 클래스 C 선언
void method() {
class C {...} // 접근 제한자 불가능 (외부 접근 x)
//객체 생성
C c = new C();
} // method() 메소드 외부에서 클래스 C 사용불가
}
Ex2)
final 특성을 가짐public class A {
public method(int arg) {
// 로컬 변수 선언
int var = 1;
// 로컬 클래스 B 선언
class B {
void method_B() {
//로컬 변수 읽기
System.out.println("arg: " + arg); (o)
System.out.println("var: " + var); (o)
//로컬 변수 수정
arg = 2; // (x)
var = 2; // (x)
// fianl 변수 변경 불가
}
}
B b = new B(); //로컬 객체 생성
b.method_B(); //로컬 객체 메소드 호출
arg = 3; // (x)
var = 3; // (x)
// 로컬 클래스 안에서 로컬 변수를 사용하고 있기 때문에 변경 불가
}
}
| 구분 | 바깥 클래스의 사용 가능한 맴버 |
|---|---|
| 인스턴스 맴버 클래스 | 바깥 클래스의 모든 필드와 메소드 |
| 정적 맴버 클래스 | 바깥 클래스의 정적 필드와 정적 메소드 |
public class A {
// A 클래스의 인스턴스 필드, 메소드 (A객체가 있어야 사용 가능)
int field_instance;
void method_instance() {...}
// A 클래스의 정적 필드, 메소드 (A객체가 없어도 사용 가능)
static int field_static;
static void method_static() {...}
// 인스턴스 맴버 클래스 B (A객체가 있어야 사용 가능)
class B {
void method_B(){
// A의 인스턴스 필드, 메소드 사용
field_instance = 10;
method_instance();
}
}
// 정적 맴버 클래스 (A객체가 없어도 사용 가능)
static class C {
void method() {
// A의 정적 필드, 메소드 사용
field_static = 10;
method_static();
}
}
}
public class A {
//A의 인스턴스 메소드
void method() {
System.out.println("A"); // A 출력
}
//인스턴스 맴버 클래스 B 선언
class B {
//B의 인스턴스 메소드
void method() {
System.out.println("B"); // B 출력
}
//B의 인스턴스 메소드
void print() {
//B 객체의 메소드 사용
this.method();
//A 객체의 메소드 사용
A.this.method();
}
}
//A의 인스턴스 메소드
void useB() {
B b = new B();
b.print();
}
}
class A {
[public | private] [static] interface B {
// 상수 필드
// 추상 메소드
// 디폴트 메소드
// 정적 메소드
}
}
public class Button {
public static interface ClickListener {
// 추상 메소드
void onClick();
}
// 필드
private ClickListener clickListener;
// 메소드
// 매개변수 타입이 인터페이스이므로 ClickListener 인터페이스를 구현한 객체를 대입
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
public void click() {
this.clickListener.onClick();
}
}
Button 클래스 이용 예제
public class ButtonExample {
public static void main(String[] args) {
//Ok 클릭 버튼 생성
Button btnOk = new Button();
class OkListener implements Button.ClickListener {
// 추상 메소드 구현하기
@override
public void onClick() {
System.out.println("Ok 버튼을 클릭했습니다.");
}
}
// Button 클래스 객체의 setClickListener() 메소드에
// ClickListener 인터페이스를 구현한 OkListener 클래스 객체를 대입
btnOk.setClickListener(new OkListener);
// Button 클래스 객체의 click() 메소드 호출
btnOk.click(); //"Ok 버튼을 클릭했습니다." 출력
}
}
익명 자식 객체
new 부모생성자(매개값, ...) { // 부모클래스를 상속 받는 익명 자식클래스를 만듦
// 필드
// 메소드
}
ex)
public class Tire {
public roll() {
System.out.println("일반 타이어가 굴러갑니다.");
}
}
public class Car {
// 필드에 Tire 객체 대입
private Tire tire1 = new Tire();
// 필드에 익명 자식 객체 대입
private Tire tire2 = new Tire() { // Tire를 상속 받은 익명 자식클래스를 만들어 대입
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 1이 굴러갑니다.");
}
};
// 메소드(필드 이용)
public void run1() {
tire1.roll(); // "일반 타이어가 굴러갑니다." 출력
tire2.roll(); // "익명 자식 Tire 객체 1이 굴러갑니다." 출력
}
// 메소드(로컬 변수 이용)
public void run2() {
Tire tire = new Tire() {
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 2가 굴러갑니다.");
}
}
tire.roll();
}
// 메소드(매개변수 이용)
public void run3(Tire tire) {
tire.roll();
}
}
Car car = new Car();
// 익명 자식 객체가 대입된 매개변수 사용
car.run3(new Tire() {
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 3이 굴러갑니다.");
}
});
익명 구현 객체
new 인터페이스() { // 인터페이스를 구현한 익명 클래스를 만듦
// 필드
// 메소드
}
ex)
public interface RemoteControl {
// 추상 메소드
void turnOn();
}
public class Home {
// 필드에 익명 구현 객체 대입
private RemoteControl rc = new RemoteControl() {
@Override
public void turnOn() {
System.out.println("TV를 켭니다.");
}
}
// 메소드(필드 이용)
public void use1() {
rc.turnOn(); // "TV를 켭니다." 출력
}
// 메소드(로컬 변수 이용)
public void use2() {
//로컬 변수에 익명 구현 객체 대입
RemoteControl rc = new RemoteControl() {
@Override
public void turnOn() {
System.out.println("에어컨을 킵니다.");
}
};
rc.turnOn(); // "에어컨을 킵니다." 출력
}
// 메소드(매개변수 이용)
public void use3(RemoteControl rc) {
rc.turnOn();
}
}
Home home = new Home();
// 익명 구현 객체가 대입된 매개변수 사용
home.use3(new RemoteControl() {
@Override
public void turnOn() {
System.out.println("난방을 킵니다.");
}
});