ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java 자바] 9. 중첩 ① 중첩 클래스
    Programming/Java 2022. 8. 9. 20:51
    반응형

    9-1. 중첩 클래스

    - 클래스 내부에 선언한 클래스로 중첩 클래스를 사용할 경우 두 클래스의 멤버를 서로 쉽게 접근할 수 있으며,
      외부에는 불필요한 관계 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있음

    - 클래스 내부에 선언되는 위치에 따라 두 가지로 분류

    선언 위치에 따른 분류 선언 위치 설명
    멤버
    클래스
    인스턴스
    멤버 클래스
    class A {
      class B {...}
    }
    A 객체를 생성해야만 사용할 수 있는 B 중첩 클래스
    정적
    멤버 클래스
    class A {
      static class B {...}
    }
    A 클래스로 바로 접근할 수 있는 B 중첩 클래스
    로컬 클래스 class A {
      void method() {
        class B {...}
      }
    }
    method()를 실행할 때만
    사용할 수 있는 B 중첩 클래스

    - 멤버클래스도 하나의 클래스이기 때문에 컴파일시 바이트 코드 파일(.class)이 별도로 생성

    A $ B . class

    - 로컬 클래스일 경우에는 다음과 같이 $1이 포함된 바이트 코드 파일이 생성됨

    A $1 B . class

    9-1-1. 인스턴스 멤버 클래스

    - 인스턴스 멤버 클래스는 인스턴스 필드, 메소드만 선언 가능 (정적 필드, 메소드 선언 불가)
    - A클래스 외부에서 인스턴스 멤버 클래스 B의 객체를 생성하려면 먼저 A의 객체를 생성하고 B 객체를 생성해야 함

    public class OuterClass {
    
      class NestedClass {
    		
        NestedClass() {}
    		
        int field1;
        void method1() {}
      }
    }
    
    public class NestedClassTest {
      public static void main(String[] args) {
        
        OuterClass a = new OuterClass();
        OuterClass.NestedClass b = a.new NestedClass();
        b.field1 = 3;
        b.method1();
      }
    }

    9-1-2. 정적 멤버 클래스

    - 정적 멤버 클래스는 모든 종류의 필드와 메소드 선언 가능
    - A클래스 외부에서 정적 멤버 클래스 C의객체 객체를 생성하기 위해서는 별도의 A객체 생성 필요 없이 진행 가능 

    public class OuterClass {
    
      static class StaticNestedClass {
    		
        StaticNestedClass() {}
        
        int field1;
        static int field2;
        void method1() {}
        static void method2() {}
      }
    }
    
    public class NestedClassTest {
      public static void main(String[] args) {
    
        OuterClass.StaticNestedClass c = new OuterClass.StaticNestedClass();
        // 일반 필드, 메소드는 객체 생성 후 객체로 호출
        c.field1 = 3;
        c.method1();
        // 정적 필드, 메소드는 클래스명으로 바로 호출
        OuterClass.StaticNestedClass.field2 = 3;
        OuterClass.StaticNestedClass.method2();
      }
    }

    9-1-3. 로컬 클래스

    - 메소드 내부에서 선언하는 중첩 클래스로, 접근제한자 및 static을 쓸 수 없음 (메소드 내부에서만 사용 가능하기 때문)

    - 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 함

    public class OuterClass {
    
      void method() {
        class LocalNestedClass {
          int field1;
          void method1() {}
        }
        
        LocalNestedClass d = new LocalNestedClass();
        d.field1 = 3;
        d.method1();
        System.out.println(d.field1);
      }
    }
    
    public class NestedClassTest {
      public static void main(String[] args) {
      
        OuterClass a = new OuterClass();
        a.method();
      }
    }

    9-2. 중첩 클래스의 접근 제한

    9-2-1. 바깥 필드와 메소드에서 사용 제한

    1) 인스턴스 멤버 클래스
    - 바깥 클래스의 인스턴스 필드의 초기값이나 인스턴스 메소드에서 객체 생성 가능
    - 바깥 클래스의 정적 필드의 초기값이나 정적 메소드에서는 객체 생성 불가

    2) 정적 멤버 클래스
    - 모든 필드의 초기값이나 모든 메소드에서 객체 생성 가능

    public class A {
    
      // 인스턴스 필드
      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 {}
    }

    9-2-2. 멤버 클래스에서 사용 제한

    1) 인스턴스 멤버 클래스
    - 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 모든 메소드 접근 가능

    2) 정적 멤버 클래스

    - 정적 멤버 클래스 안에서는 바깥 클래스의 정적 필드와 정적 메소드에만 접근 가능

    public 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;		// 접근 불가
         //method1();		// 접근 불가
         
         field2 = 10;
         method2();
        }
      }
    }

    9-2-3. 로컬 클래스에서 사용 제한

    - 로컬클래스에서 사용되는 매개 변수와 로컬 변수는 모두 final의 특성을 갖게 되며, 값 수정이 불가해짐

    public class OuterClass {
    
      public void method1(int arg) {
        int localVariable = 1;
        //arg = 100;
        //localVariable = 100;
        class Inner {
          public void method() {
            int result = arg + localVariable;
            System.out.println(result);
          }
        }
        
        Inner i = new Inner();
        i.method();
      }
    	
      public static void main(String[] args) {
        OuterClass a = new OuterClass();
        a.method1(50);
      }
    }

    9-2-4. 중첩 클래스에서 바깥 클래스 참조 얻기

    - 중첩 클래스에서 this키워드는 중첩 클래스의 객체 참조를 의미
    - 중첩 클래스 내부에서 바깥 클래스의 객체 참조를 얻으려면 바깥 클래스 이름을 this 앞에 붙여주면 됨

    public class Outter {
      String field = "Outter-field";
      
      void method() {
        System.out.println("Outter-method");
      }
      
      class Nested {
        String field = "Nested-field";
        void method() {
          System.out.println("Nested-method");
        }
        
        void print() {
          // 중첩객체 참조
          System.out.println(this.field);
          this.method();
          
          // 바깥객체 참조
          System.out.println(Outter.this.field);
          Outter.this.method();
        }
      }
    }
    
    public class OutterTest {
      public static void main(String[] args) {
        Outter outter = new Outter();
        Outter.Nested nested = outter.new Nested();
        nested.print();
      }
    }

     

    반응형

    댓글

Designed by Tistory.