(3월 10일)
public class A {
class B {
// 인스턴스 멤버 클래스
// 접근 방식에 따라 외부에서 사용할 수 있는 범위가 다름
// public : 다른 패키지에서도 사용 가능
// (default) :
}
}
A클래스의 인스턴스 멤버 클래스 B
package ch09.sec02.exam01;
public class A {
class B {
// 인스턴스 멤버 클래스 : 클래스 A 내부에 정의된 일반적인 내부 클래스
// 주로 private를 사용하여 외부에서 직접 접근을 막음
// A클래스 내부에 있는 B클래스의 객체는 인스턴스 멤버 클래스 이므로
// 인스턴스 외부 클래스의 멤버변수나, 생성자, 메소드에서만 생성 가능
}
B field = new B();
// A클래스의 인스턴스 필드에 B 객체 생성 가능
// A의 인스턴스가 존재해야 field가 생성 가능
A(){
B b = new B();
}
// 기본생성자 A를 통해 B객체를 생성하여 호출할 수 있음
void method() {
B b = new B();
}
// 클래스 내부의 메소드에서도 B 객체 생성 가능
}
실행문
package ch09.sec02.exam01;
public class Aexam {
public static void main(String[] args) {
A a = new A();
// B클래스는 A의 인스턴스 멤버 클래스이다.
// 정적(static)인 객체가 아니기 때문에
// 외부클래스 A의 객체가 존재해야 생성이 가능하다
A.B b = a.new B();
// 외부클래스.내부클래스 참조변수(내부) = 참조변수(외부).new 내부클래스명();
// 인스턴스 a를 통해 B객체를 생성하는 과정
}
}
A의 인스턴스 멤버 클래스 B
package ch09.sec02.exam02;
public class A {
// class B : A의 인스턴스 멤버 클래스
class B {
int field1 = 1;
// 인스턴스 필드 선언
static int field2 = 2;
// 정적 필드 선언 (Java 17 부터 가능)
B(){
System.out.println("B-생성자 실행");
}
// B() 생성자
void method1() {
System.out.println("B-method1 실행");
}
// 인스턴스 메소드
static void method2() {
System.out.println("B-method2 실행");
}
// 정적 메소드 (Java 17 부터 가능)
}
// A 클래스의 인스턴스 메소드
void useB() {
// B 객체 생성
B b = new B();
// 인스턴스 필드
System.out.println(b.field1);
// 메소드 사용
b.method1();
// 정적 필드 선언 : static을 사용했기 때문에 해당 클래스명을 그대로 명시해주기
System.out.println(B.field2);
// 정적 메소드 선언 : static을 사용했기 때문에 해당 클래스명을 그대로 명시해주기
B.method2();
}
}
클래스 실행
package ch09.sec02.exam02;
public class AExample {
public static void main(String[] args) {
A a = new A();
// A 객체 생성함으로서 A 인스턴스 사용 가능
a.useB();
// A의 인스턴스 메소드 useB 호출함으로서
// useB 내부에 생성된 B객체를 사용할 수 있음
}
}
public class A {
static class B {
// 정적 클래스이기 때문에 A 객체가 존재하지 않아도 됨
}
}
A 클래스 내부의 정적 멤버 클래스 B
package ch09.sec03.exam01;
public class A {
static class B{
// 정적 멤버 클래스 선언
// 정적 클래스이기 때문에 A객체를 생성하지 않아도 사용가능
// 정적 멤버 클래스는 외부 클래스 어디에서든 생성 가능
}
B field1 = new B();
// B 객체를 인스턴스 필드에 생성
static B field2 = new B();
// 정적 필드 값으로 B 객체를 대입함
// B가 정적 클래스이기 때문에 정적 필드에 객체 생성 가능
A(){
B b = new B();
}
// 생성자 A에 B 객체 생성
// A 생성자를 통해 B 객체를 호출할 수 있음
void method1() {
B b = new B();
}
// 인스턴스 메소드에 B 객체 생성
static void method2() {
B b = new B();
}
// 정적 메소드에 B 객체 생성
// B가 정적 클래스이기 때문에 정적 메소드에 객체 생성 가능
}
B 객체 생성
package ch09.sec03.exam01;
public class AExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
A.B b = new A.B();
// A클래스 내부에 있는 B 객체 생성
// B클래스는 정적 멤버 따로 외부클래스(A)를 생성할 필요가 없고
// 독립적으로 생성이 가능함
}
}
정적 멤버 클래스에 인스턴스, 정적 필드, 메소드 등 생성
package ch09.sec03.exam02;
public class A {
// 정적 멤버 클랫
static class B {
int field1 = 1;
// 인스턴스 필드 생성
static int field2 = 2;
// 정적 필드 생성 (Java 17부터 가능)
B(){
System.out.println("B-생성자");
}
// B 생성자 선언
void method1() {
System.out.println("B-method1");
}
// 인스턴트 메소드 생성
static void method2() {
System.out.println("B-method2");
}
// 정적 메소드 생성 (Java 17부터 가능)
}
}
실행 클래스
package ch09.sec03.exam02;
public class AExample {
public static void main(String[] args) {
A.B b = new A.B();
// A클래스 내부에 있는 B 객체 생성
// B가 정적 멤버 클래스이기 때문에 외부 클래스를 따로 생성할 필요 없이
// 독립적으로 생성이 가능함
System.out.println(b.field1);
// B 객체에 저장된 field1 값 호출
// 인스턴스 필드를 호출하는 것이기 때문에 참조변수를 통해 선언
b.method1();
// B 객체에 저장된 method1 호출
// 인스턴스 메소드를 호출하는 것이기 때문에 참조변수를 통해 선언
System.out.println(A.B.field2);
// B 객체에 저장된 field2 값 호출
// 정적 필드를 호출하는 것이기 때문에 클래스를 통해 선언
A.B.method2();
// B 객체에 저장된 method2 메소드 호출
// 정적 메소드를 호출하는 것이기 때문에 클래스를 통해 선언
}
}
public class A {
// 생성자
public A() {
class B { }
}
// 메소드
public void method() {
class B { }
}
}
메소드 내부에 생성된 로컬 클래스
package ch09.sec04.exam02;
public class A {
void useB() {
// 로컬 클래스
class B {
int field1 = 1;
static int field2 = 2; // java 17 부터 가능
B(){
System.out.println("B 생성자");
}
void method1() {
System.out.println("B-method1");
}
static void method2() {
System.out.println("B-method2");
} // java 17 부터 가능
}
B b = new B();
// 메소드 내부에서 로컬 클래스 생성 가능
System.out.println(b.field1);
b.method1();
// 인스턴스 필드 및 메소드 선언
System.out.println(B.field2);
B.method2();
// 정적 필드 및 메소드 선언
}
}
실행 클래스
package ch09.sec04.exam02;
public class AExample {
public static void main(String[] args) {
A a = new A();
// A 객체 생성
a.useB();
// A 클래스 내부에 생성된 useB 메소드 안에
// 로컬 클래스 B가 생성되었기 때문에
// useB 메소드를 선언함으로서 B 객체를 생성할 수 있음
}
}
package ch09.sec04.exam03;
public class A {
public void method1(int arg) {
int var = 1;
// int arg, var : 지역 변수
// Java에서 로컬 변수는 fianl로 취급함
class B {
void method2() {
System.out.println("arg: " + arg);
System.out.println("var: " + var);
// 지역 변수 출력
// 지역 변수를 로컬 클래스 내부에서 사용 가능
// 하지만 지역 변수는 로컬 클래스에 접근할 때 final의 형태로 변환되므로
// 값을 수정할 수 없음
// arg = 2;
// var = 2;
}
}
B b = new B();
b.method2();
// 지역 변수는 final 취급이 되었으므로 값 변경 안됨
// arg = 3;
// var = 3;
}
}
package ch09.sec05.exam01;
public class A {
// A의 인스턴스 필드와 메소드
int field1;
void method1() { }
// A의 정적 필드와 메소드
static int field2;
static void method2() { }
// 인스턴스 멤버 클래스
class B{
void method() {
// A의 인스턴스 필드와 메소드 사용
field1 = 10;
method1();
// A의 정적 필드와 메소드 사용
field2 = 10;
method2();
}
// 인스턴스 멤버 클래스에는 바깥 클래스의 정적, 인스턴스 필드, 메소드 등 모두 선언 가능
}
static class C {
void method() {
// A의 인스턴스 필드와 메소드 사용
// field1 = 10;
// method1();
// A의 정적 필드와 메소드 사용
field2 = 10;
method2();
}
// 정적 멤버 클래스에는 바깥 클래스의 정적 필드, 메소드 등만 선언 가능
}
}
package ch09.sec05.exam02;
public class A {
// A의 인스턴스 필드
String field = "A-field";
// A의 인스턴스 메소드
void method() {
System.out.println("A-method");
}
class B{
// B의 인스턴스 필드
String field = "B-field";
// B의 인스턴스 메소드
void method() {
System.out.println("B-method");
}
// B의 인스턴스 메소드
void print() {
// this문의 경우 현재 객체에 있는 필드를 선언하기 때문에
// B 객체의 필드와 메소드를 사용함
System.out.println(this.field);
this.method();
// A.this : A 클래스 객체에 있는 필드를 선언함
// A 객체의 필드와 메소드를 사용
System.out.println(A.this.field);
A.this.method();
}
}
// A의 인스턴스 메소드
void useB() {
B b = new B();
b.print();
}
}
실행 클래스
package ch09.sec05.exam02;
public class AExam {
public static void main(String[] args) {
A a = new A();
a.useB();
// useB 메소드 내부에서 B 객체가 생성됨
}
}
(3월 11일)
package ch09.sec06;
public class Button {
// 정적 멤버 인터페이스
public static interface ClickListener {
void onClick();
// 추상 메소드
}
// 필드 생성
// 인터페이스는 객체 생성이 불가하므로 참조변수 형태로 선언해야함
private ClickListener clickListener;
// 인터페이스 대입 메소드
// 인터페이스의 필드를 매개변수로 사용
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
// 입력받은 매개변수를 인터페이스 필드에 대입
}
// 인터페이스 동작 메소드
// 버튼이 눌렸을 때 동작함
public void click() {
this.clickListener.onClick();
}
}
package ch09.sec06;
public class ButtonExam {
public static void main(String[] args) {
Button btnOk = new Button();
// OK 버튼 참조변수에 Button 객체 생성 (OK 버튼 생성)
// Button 클래스의 ClickListener 인터페이스 참조
// 인터페이스를 객체로 만들 수 없기 때문에 인터페이스 자체를 사용할 객체 생성
// OK버튼 실행 클래스
class OkListener implements Button.ClickListener {
// ClickListener 인터페이스의 onClick 메소드 재정의
@Override
public void onClick() {
System.out.println("OK 버튼을 생성했습니다.");
}
}
// OkListener 객체를 setClickListener 메소드의 매개변수로 사용
btnOk.setClickListener(new OkListener());
// click 메소드 실행 및 ok 버튼 클릭
btnOk.click();
// Cancel 버튼 참조변수에 Button 객체 생성(Cancel 버튼 생성)
Button btnCancel = new Button();
// Button 클래스의 ClickListener 인터페이스 참조
// Cancel버튼 실행 클래스
class CancelListener implements Button.ClickListener {
// ClickListener 인터페이스의 onClick 메소드 재정의
@Override
public void onClick() {
System.out.println("Cancel 버튼을 클릭함");
}
}
// CancelListener 객체를 setClickListener 메소드의 매개변수로 사용
btnCancel.setClickListener(new CancelListener());
// click 메소드 실행 및 cancel 버튼 클릭
btnCancel.click();
}
}
new 부모생성자 {
// 필드
// 메소드
}
package ch09.sec07.exam01;
public class Tire {
// roll 메소드 선언
public void roll() {
System.out.println("일반 타이어가 굴러갑니다");
}
}
package ch09.sec07.exam01;
public class Car {
private Tire tire1 = new Tire();
// 익명 객체 : 익명 클래스를 객체를 생성하여 참조변수에 바로 대입
// 객체를 일회성으로 사용할 경우에 용이함
private Tire tire2 = new Tire() {
// 익명 객체에서 메소드 재정의함
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 1이 굴러갑니다");
}
};
// 사실상 값의 형태이기 때문에 세미콜론을 붙여줘야함
public void run1() {
tire1.roll();
tire2.roll();
}
public void run2() {
// 익명 객체 생성
Tire tire = new Tire() {
// Tire 클래스의 roll() 메소드를 재정의함
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 2가 굴러갑니다");
}
};
// 값의 형태이기 때문에 세미콜론을 붙여줘야함
tire.roll();
}
public void run3(Tire tire) {
tire.roll();
}
}
package ch09.sec07.exam01;
public class CarExample {
public static void main(String[] args) {
Car car = new Car();
car.run1();
car.run2();
// 메소드에도 익명 객체를 선언할 수 있음
// 객체를 일회용으로 사용할 때 주로 사용
car.run3(new Tire() {
// Tire 객체의 roll 메소드를 재정의함
@Override
public void roll() {
System.out.println("익명 자식 Tire 객체 3이 굴러갑니다.");
}
});
}
}
형태
new 인터페이스(){
//필드
//메소드
}
package ch09.sec07.exam02;
public interface RemoteControl {
// 인터페이스의 추상메소드 선언
void turnOn();
void turnOff();
}
package ch09.sec07.exam02;
public class Home {
// 익명 구현 객체 : 익명으로 객체를 생성하여 그 안의 메소드를 직접 구현하는 것
// 인터페이스는 원래 객체 생성이 불가능하나 익명 구현 객체는
// 인터페이스를 구현한 이름 없는 클래스의 인스턴스이기 때문에 객체 생성이 가능
// 인터페이스나 추상메소드를 구현할 때 주로 사용
private RemoteControl rc = new RemoteControl() {
public void turnOn() {
System.out.println("TV를 켭니다");
}
public void turnOff() {
System.out.println("TV를 끕니다");
}
};
// 값의 형태이기 때문에 꼭 세미콜론 붙여주기
public void use1() {
rc.turnOn();
rc.turnOff();
}
public void use2() {
// 추상메소드를 구현하기 위해 익명 구현 객체 생성
RemoteControl rc = new RemoteControl() {
// 메소드 재정의
@Override
public void turnOn() {
System.out.println("에어컨을 켭니다");
}
// 메소드 재정의
@Override
public void turnOff() {
System.out.println("에어컨을 끕니다");
}
};
rc.turnOn();
rc.turnOff();
}
public void use3(RemoteControl rc) {
rc.turnOn();
rc.turnOff();
}
}
package ch09.sec07.exam02;
public class HomeExample {
public static void main(String[] args) {
Home home = new Home();
home.use1();
home.use2();
// 익명 객체 생성을 통해 추상 메소드를 재정의할 수 있음
home.use3(new RemoteControl() {
@Override
public void turnOn() {
System.out.println("난방을 합니다");
}
@Override
public void turnOff() {
System.out.println("난방을 끕니다");
}
});
}
}