Java언어 스터디 Chapter9-1(중첩클래스와 중첩인터페이스)

최재하·2022년 12월 4일
1

중첩클래스란?

클래스 내부에 선언한 클래스를 말합니다.
중첩 클래스를 사용하면 두 클래스의 멤버들은 서로 쉽게 접근할 수 있고, 외부에는 불필요한 관계 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있습니다.

class ClassName{
	class NestedClassName{ //중첩클래스
    }
}

중첩클래스

중첩 클래스는 선언되는 위치에 따라 두 가지로 분류됩니다.

  • 클래스의 멤버로서 선언되는 중첩 클래스를 멤버 클래스라고 하고, 멤버클래스는 클래스나 객체가 사용 중이라면 재사용이 가능합니다.
  • 메소드 내부에서 선언되는 중첩 클래스를 로컬 클래스라고 하고, 로컬 클래스는 메소드를 실행할 때만 사용하고 메소드가 종료되면 없어집니다.


멤버 클래스

  • 인스턴스 멤버 클래스

    static키워드 없이 중첩 선언된 클래스.
    인스턴스 필드와 메소드만 선언이 가능하고, 정적 필드와 메소드는 선언할 수 없습니다.
    class A{
        //인스턴스 멤버 클래스
        class B{
            B(){};					//생성자
            int field1;				//인스턴스필드
            //static int fidle2;	//정적필드x
            void method1(){};		//인스턴스메소드
            //static void method2(){};//정적메소드 x
        }
    }

  • 정적 멤버 클래스

    정적 멤버 클래스는 static키워드로 선언된 클래스.
    정적 멤버 클래스는 모든 종류의 필드와 메소드 선언가능.
    class A{
        //정적멤버클래스
        static class C{
            C(){};					//생성자
            int field1;				//인스턴스필드
            static int field2;		//정적필드
            void method1(){};		//인스턴스메소드
            static void method2(){};//정적메소드
        }
    }


로컬 클래스

메소드내에서 선언한 중첩 클래스를 로컬 클래스라 합니다.
접근제한자(public,private)및 static을 사용할 수 없다. 로컬클래스는 메소드내에서만 사용되기 때문에 접근을 제한할 필요가 없기때문이다.

void method(){
	//로컬클래스
    class D{
    	D(){};						//생성자
        int field1;					//인스턴스필드
        //static int field2;		//정적필드x
        void method1(){};			//인스턴스메소드
        //staitc void method2(){};	//정적메소드x
    }
    D d = new D();
    d.field1 = 3;
    d.method1();
}

로컬 클래스는 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 한다.
주로 다음과 같이 비동기 처리를 위해 스레드 객체를 만들 때 사용한다.

void method(){
	class DownloadThread extends Thread{...}
    Downloadthread thread = new DownloadThread();
    thread.start();
}


중첩클래스의 접근제한

  • 바깥필드와 메소드에서 사용제한

    public classA{
    	//인스턴스필드
      	B field1 = new B();		//(O)
      	C field2 = new C();		//(O)
        
        //인스턴스메소드
        void method1(){
        	B var1 = new B();	//(O)
          	C var2 = new C();	//(O)
        }
        
        //정적필드초기화
        //static B field3 = new B();	//(x)
        static C field4 = new C();		//(O)
        
        //정적메소드
        static void method2(){
          //B var1 = new B();	//(x)
          C var2 = new C();		//(O)
        }
        //인스턴스멤버클래스
        class B{}
        //정적멤버클래스
        static class C{}
    }

    인스턴스 멤버 클래스B는 바깥 클래스의 인스턴스필드의 초기값이나 인스턴스 메소드에서 객체를 생성할 수 있으나, 정적필드의 초기값이나 정적 메소드에서는 객체를 생성할 수 없다.
    정적 클래스C는 모든 필드의 초기값이나 모든 메소드에 객체를 생성 가능합니다.


  • 멤버 클래스에서 사용 제한

    멤버 클래스가 인스턴스 또는 정적으로 선언됨에 따라 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드에 접근할 때에도 제한이 따른다.

    class A{
    	int field1;
      	void method1(){...}
        
        static int field2;
        static void method2(){...}
        
        class B{
        	void method(){
          		field1 = 10;
                method1();
                  
                field2 = 10;
                method2();
          	}
        }
        
        static class C{
        	void method(){
          		//field1 = 10;	//(x)
                //method1();	//(x)
                  
                field2 = 10;
                method2();
          	}
        }
    }

    인스턴스 멤버 클래스B안에서는 바깥 클래스의 모든 필드와 모든메소드에 접근할 수 있다.
    정적 멤버 클래스C안에서는 바깥클래스의 정적필드와 메소드에만 접근 가능하고 인스턴스 필드와 메소드에는 접근이 불가능합니다.


  • 로컬클래스에서 사용 제한

    로컬 클래스의 객체는 메소드 실행이 종료되면 없어지는 것이 일반적이지만 메소드가 종료되어도 계속 실행 상태로 존재할 수 있다, 로컬 스레드 객체를 사용할때 메소드를 실행하는 스레드와 다르므로 메소드가 종료된 후에도 로컬 스레드 객체는 실행상태로 존재할 수 있다.


    이 문제를 해결하기 위해 컴파일 시 로컬 클래스에서 사용하는 매개 변수나 로컬 변수의 값을 로컬 클래스 내부에 복사해두고 사용한다. 그리고 매개 변수나 로컬 변수가 수정되어 값이 변경되면 로컬 클래스에 복사해둔 값과 달라지므로 매개 변수나 로컬 변수를 final로 선언해서 수정을 막아준다.
    로컬 클래스에서 사용가능한 것은 final로 선언된 매개변수와 로컬변수 뿐이다.


    자바7 이전까지는 final키워드 어벗이 선언된 변수를 로컬클래스에서 사용 하면 컴파일 에러가 발생했지만 자바8부터는 final키워드 없이 선언된 매개변수와 로컬변수를 사용해도 컴파일 에러가 발생하지 않습니다.

    자바8부터는 final선언을 하지않아도 값이 수정되지 않도록 fianl의 특성을 부여해줍니다.


  • 중첩클래스에서 바깥클래스 참조 얻기

    클래스 내부에서 this는 객체 자신의 참조이다. 중첩 클래스에서 this키워드를 사용하면 바깥클래스의 객체 참조가 아니라 충첩 클래스의 객체 참조가 됩니다.
    바깥클래스.this.필드
     바깥클래스.this.메소드();
    중첩 클래스 내부에서 바깥 클래스의 객체 참조를 얻으려면 바깥 클래스의 이름을 this앞에 붙여주면 됩니다.

중첩 인터페이스

클래스의 멤버로 선언된 인터페이스를 말합니다. 인터페이스를 클래스 내부에 선언하는 이유는 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서입니다.

class A{
	[static] interface I { //중첩인터페이스
    	void method();
    }
}

중첩 인터페이스는 인스턴스멤버와 정적멤버모두 가능합니다.
인스턴스멤버 인터페이스는 바깥 클래스의 객체가 있어야 사용 가능하며, 정적멤버 인터페이스는 바깥 클래스의 객체 없이 바깥 클래스만으로 바로 접근이 가능합니다.

0개의 댓글