[Java] 중첩 클레스 알아보기

     

    🍁 중첩 클레스

    ✔️ class안에 class를 의미한다.

    ✔️ class 안에 class가 있어서 Inner Class라고도 부르기도 한다.

     

     

     

    🍁 중첩 클레스 종류

    분류 설명
    인스턴스 멤버 클레스 A 객체가 선언 되었을 때, 그 안의 B객체가 존재한다.
    A 객체에 접근하고 B 객체에 접근할 수 있다.
    정적 멤버 클레스 A 객체와 상관없이 B 객체가 이미 만들어져 있다. ( static )
    A 객체에 접근하지 않아도 B 객체에 접근할 수 있다.
    로컬 클레스 A 객체 안의 method 혹은 생성자에서 B 객체에 접근할 수 있다.

     

    ✔️ 중첩 클레스에서 먼저 파악할 것은 '멤버'라는 명칭이다. class 안의 class를 의미한다. 우리가 생각하는 Inner Class이다.

     

    여기에는 익명 클레스도 존재하지만, 이는 다음장에서 다룰 예정이다.

    이유는 익명클레스는 중첩클레스 이되, 사용방법이 다르기 때문이다.

     

     

      인스턴스 멤버 클레스

    class Outer {
    
    	class Inner {
        
        }
    }

    ✔️ Inner class에 접근하기 위해서는 Outer class를 접근해야 가능하다.

     

     

    class 안에 class를 두는 기본적인 모습인데, 이는 외부에서의 class 접근을 막는다.

    이를 하는 이유는 외부의 공유 목적이 아닌, 해당 class 내에서만 사용하기 위한 목적이 가장 크다.

     

    클레스는 기능별로 역할을 분리 시켜야 하고, 분리를 시킨 클레스는 다른 클레스의 접근을 허용한다.

    이는 전체적인 코드 작성에 별다른 영향을 끼치지는 않지만, 향후 클레스가 많아질수록 더 복잡해 질 수 있기 때문에 클레스 관리에는 절대 도움이 되지 않는다.

     

    즉, 객체지향 언어의 특징이 객체의 분할인데 너무 분할하면 패키지 내부의 클레스가 너무 많아진다는 단점이 존재한다.

    그러므로 해당 클레스에서만 사용이 된다면, 굳이 외부에 만들 필요가 없으므로 내부 클레스를 이용한다.

     

     

     

    📕 인스턴스 멤버 클레스 예시 코드 확인해 보기

    public class InnerClassB {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		//InnerClass01의 위치를 정의하기 위해서 OutClass 위치를 지정해주었다.
     		//OutClass를 작성하기 싫다면, import해서 호출 하는 방법도 있다.
    		OutClass outClass = new OutClass();
    		OutClass.InnerClass01 innerClass = outClass.new InnerClass01();
            
     		//각각 method 호출 하기
            outClass.print();
    		innerClass.print();
    	}
    
    }
    
    //외부 클레스
    class OutClass {
    	
    	//내부 클레스
    	class InnerClass01 {
    		public void print() {
    			System.out.println("Inner Class");
    		}
    	}
    	
    	public void print() {
    		System.out.println("OutClass");
    		InnerClass01 innerClass01 = new InnerClass01();
    		innerClass01.print();
    	}
    }

    main 함수에서 InnerClass01에 접근하기 위해서 OutClass에 우선적으로 접근하는 것을 확인할 수 있다.

     

    ✔️ InnerClass01을 접근하기 위해서는 반드시 OutClass를 접근해야 가능하다.

     

     

      정적 멤버 클레스

    class OutClass {
    
    	static class InnerClass {
     	
        }
    }

    ✔️ 인스턴스 멤버 클레스와 사용 방법은 비슷하지만, class 앞에 static이 선언 되어 있다.

     

     

     

    📕 정적 멤버 클레스 예시 코드 확인해 보기

    public class InnerClassC {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		OutClass02 outClass02 = new OutClass02();
    		//OutClass02.InnerClass02 inner01 = outClass02.InnerClass02();
    		OutClass02.InnerClass02 inner02 = new OutClass02.InnerClass02();
    		inner02.print();
    		outClass02.print();
    	}
    
    }
    
    class OutClass02 {
    	
    	String name = "OutClass02 변수";
    	static String staticName = "OutClass02 static변수";
    	
    	static class InnerClass02 {
    		public void print() {
    			System.out.println("InnerClass02");
    			//static이 아닌 변수에는 접근이 불가능하다.
    			//System.out.println(name);
    			System.out.println(staticName);
    		}
    	}
    	
    	public void print() {
    		System.out.println("OuterClass");
    		InnerClass02 innerClass02 = new InnerClass02();
    		innerClass02.print();
    	}
    }

    💯 인스턴스와 정적의 차이는 외부에서 InnerClass의 접근 차이에 있다. OutClass 상관없이 InnerClass만 필요로 하여 접근이 필요할 때 static을 이용한다.

     

     

    ✔️  InnerClass에 직접 접근하므로, OutClass의 내용과 공유가 불가능하다.

    ✔️ OutClass와 공유하기 위해서는 static으로 선언되어 있어야 한다.

     

     

    ✔️ static을 선언함으로써, 외부에서 InnerClass 접근할 때 인스턴스 멤버 클레스와 차이가 존재한다.

     

     

    내부 클레스를 만들었지만, 외부에서 내부클레스를 접근의 필요가 느껴질 때 이용된다.

     

     

     

      로컬 클레스

    class OutClass {
    
     public void method() {
     
       //Inner Class가 Method에 속해 있을 경우
       class InnerClass {
       
       }
     
     }
    
    
    }

    ✔️  InnerClass가 생성자 혹은 method에 선언되어 있다.

     

    ✔️  method에서만 해당 class가 필요할 때 이용 된다. 외부에서의 class 접근용으로 사용하지 않는다.

     

     

     

    📕 로컬 클레스 예시 코드 확인해 보기

    public class LocalClass {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		LocalClass localClass = new LocalClass();
    		localClass.method();
    	}
    	String localClassName = "LocalClassName1";
    	
    	public void method() {
    		class InnerB {
    			int num;
    			
    			public void printA() {
    				System.out.println(localClassName);
    			}
    		}
    		
    		InnerB innerB = new InnerB();
    		innerB.num = 10;
    		System.out.println(innerB.num);
    		innerB.printA();
    	}
    	
    	//local class는 다른 method에서 선언 된 변수는 접근할 수가 없다.
    	public void method2() {
    		int num = 100;
    	}
    
    }


    ✔️
      method에서만 사용할 때, method에서 선언한다.

     

     

     

     

      그럼 왜 사용할까

    ✔️  객체 지향 언어의 특징을 살리면서, class를 생성할 수 있다.

    ✔️  해당 class에서만 사용하므로, 다른 패키지에서 내부class의 접근을 최소화 한다.

    ✔️  코드 관리가 편하다.

     

     

    객체 지향 언어의 특징은 코드의 분할 입니다.

    그러나 코드가 분할 될수록 class 파일은 점차 많아지는 불편함도 생겨납니다.

     

    자, 이게 무슨 소리인가? 할 수 있습니다.

    만약, 앞에 펜이 있다고 가정을 한다면 펜을 정리하기 위해서는 보통 필통을 이용합니다.

    그리고 필통을 찾음으로써, 펜을 꺼낼 수 있습니다.

     

    그런데 운동을 나선다고 가정했을 때 펜이 꼭 필요한가? 라고 한다면 아닙니다.

    펜도 필요한 상황이 있지만, 운동을 하는 순간 만큼은 펜은 필요가 없습니다.

     

    그런데 java에서는 펜을 찾을 것인지를 묻습니다. 이유는 운동이 펜하고 연관이 없다는 것을 모르기 때문입니다.

    이런 문제는 class가 생겨날수록 비슷한 사례가 점차 생겨납니다.

     

    그래서 우리는 관련된 class끼리 묶기 위해서 중첩클레스를 이용합니다.

    사용은 하되, 호출을 억제함으로써 코드 자동 완성을 최소화 합니다.

    반응형

    'Language > JAVA' 카테고리의 다른 글

    [Java] 디자인 패턴, Strategy에 대해서 알아보자  (1) 2024.09.07
    [JAVA] 디자인패턴 - 싱글턴  (0) 2024.09.02
    [Java] 상속  (0) 2024.06.23
    [Java] Java 설치하기  (0) 2024.04.29
    [Java] 문자열 관리하기  (1) 2023.11.23

    댓글

    Designed by JB FACTORY