15-Nested Class
중첩 클래스(nested class)
- 중첩클래스 : 클래스 내부에 완전한 클래스가 구성될 수 있다.
class A{ // > Outer class
//멤버변수
//메소드(){지역변수}
//생성자
class B{ // > Inner class (중첩 클래스)
//멤버변수
//메소드(){지역변수}
//생성자
}
}
왜 포함을 시켜 쓰는가?
- 특정한 클래스를 한 클래스 내에서 한정해서 쓰고싶을 때
class A{
B b1 = new B();
class B{ }
}
class C{ B b1 = new B(); // > 오류
A.B b1 = new A().newB(); // 가능
}
경우 1)
Interface I1 ( mi1(); )
Interface I2 ( mi2(); )
Interface I3 ( mi3(); )
class F{
f1(){}
f2(){}
}
class D extends F implemnets I1, I2, I3{
mi1(){overriding}
mi2(){overriding}
mi3(){overriding}
// overriding 의무
f1(){}
f2(){}
// 선택적 overriding
// 추가 메소드
d1(){ }
}
// D class 안 메소드가 6개
----------------------------------
//클래스 안의 클래스 - 명확한 명시가 가능.
//중첩 인터페이스도 가능. (다른 클래스 내부에 포함된 인터페이스)
class D extends F implemnets I1, I2, I3{
class I1sub implements I1{
mi1(){overriding}
}
class I2sub implements I1{
mi2(){overriding}
}
class I3sub implements I1{
mi3(){overriding}
}
class FSub extends F{
f1(){}
f2(){}
// 선택적 overriding
}
// 추가 메소드
d1(){ }
}
경우2)
package day8;
class Outer{
class Inner{ // non-ststic(=인스턴스) 멤버중첩클래스
void m() {
System.out.println("중첩클래스 메소드 실행");
}
}
static class Inner2{ // static 멤버 중첩 클래스
void m2() {
System.out.println("중첩클래스 메소드 실행2");
}
}
void test() {
//지역 중첩 클래스
class Inner3{
void m3() {
System.out.println("중첩클래스 메소드 실행3");
}
}
new Inner3().m3(); // 지역변수처럼 쓰이는 중첩 클래스에 대한 객체를 만들고, 호출도 이 안에서 해야
}
}
//이너클래스는 멤버변수처럼 사용되기 때문에 static 가능
public class InnerTest1 {
public static void main(String[] args) {
// Inner i = new Inner(); --- Outer class 안에 있는 것, 단독으로 객체 만들기 불가
Outer o = new Outer();
Outer.Inner i = o.new Inner();
// =- Outer.Inner i = new Outer().new Inner();
i.m();
Outer.Inner2 i2 = new Outer.Inner2(); // static일 경우
i2.m2();
o.test();
}
}
-
static은 객체가 생성되기 전에 메모리에 생성(미리 메모리 할당, 그래서 공유 가능), 객체를 만들면서 만들거나 이후에 만드는 것은 따라서 불가능하다.
-
중첩클래스 중에서 instance 멤버클래스를 가지고 static 변수, static 메소드를 취급해서는 안된다. 사용이 불가.
- static : 객체 생성 이전(프로그램 최초 시작) 메모리 할당 저장
- 객체 1개 값만 공유, 이후 사용시 클래스명.xxx
- static 중첩 내부 클래스 -> static 메소드 가능
- 중첩내부클래스 - > static 메소드 불가
- static끼리 정의된 것은 그것들끼리. // 메모리생성시기를 생각해보면 된다.
- instance 멤버 내부 클래스 / 인터페이스
- static 멤버 내부 클래스 / 인터페이스
- 메소드 내부 - 지역 내부 클래스 / 인터페이스
- 익명 내부 클래스 - 상속 인터페이스 구현, 객체 생성 / 인터페이스
- 인터페이스
class A{
class B{void m(){}}
interface I{mi();}
class C implements I{ mi(){ overriding } }
// I 인터페이스 상속받은 하위클래스를 C라는 클래스로 정의
}
- 익명 객체
class A{
class B{void m(){}}
interface I{mi();}
class C implements I{ mi(){ overriding } }
// I 인터페이스 상속받은 하위클래스를 C라는 클래스로 정의
}
-- main
C c1 = new C();
c1.mi();
I x = new I() {mi(){overriding}}
// I 인터페이스 상속받은 하위클래스를 익명의 클래스로 정의
// I 인터페이스 타입의 익명 객체를 생성한 것
// 익명 클래스 정의와 객체 생성이 교차되어있는 표현.
new I(){mi(){ovrriding}}.mi(); // 위와 같이 가능
// 익명클래스는 딱 한 번만 객체를 생성해서 쓸 것이라는 뜻, 다른 곳에서 사용하지 않음.
x.mi();
상위클래스나 인터페이스명 변수 = new 상위클래스나 인터페이스명(){
상위클래스나 인터페이스 상속 하위클래스 정의 ( = 무명 )
추가멤버변수
추가메소드
상속오버라이딩
}
example
//무명객체
//interface Runnable { public void run(); }
class RunnableSub implements Runnable{
public void run() {
System.out.println("실행중");
}
}
Runnable sub = new RunnableSub(); // 상위클래스 인터페이스 형변
//메소드 호출
Thread t1 = new Thread(sub);
t1.start();
// 다음의 익명객체는 위와 같음
new Thread(new Runnable() {
public void run() {
System.out.println("실행중");
}
}).start();
익명객체는 딱 한 번만 사용할것. 매소드는 하나일때가 유용하다
interface myInter {
void mi1();
void mi2();
}
---- main ----
new myInter(){
public void mi1() {
System.out.println("mi1");
}
public void mi2() {
System.out.println("mi2");
}
}.mi1();
new myInter(){
public void mi1() {
System.out.println("mi1");
}
public void mi2() {
System.out.println("mi2");
}
}.mi2();
// 2개의 메소드를 호출할 경우 익명객체는 이렇게 두 번을 작성해야 한다.
// 이 경우, 다음과 같은 식이 더 나으
myInter i = new myInter(){
public void mi1() {
System.out.println("mi1");
}
public void mi2() {
System.out.println("mi2");
}
};
i.mi1();
i.mi2();