본문 바로가기
Java

Inner class 알아보기

by GGShin 2022. 5. 9.

Inner class(내부 클래스)는 단어에서 알 수 있다시피 클래스나 인터페이스 내부에 선언된 클래스를 의미합니다.

정확히 구분하면 Java에는 크게 4가지 종류의 nested class가 있는데 (nested라고 하면 어떤 물체 안에 들어가 있는 형태를 이야기 합니다. 어찌보면 단어의 의미 자체는 inner랑 유사하죠) 바로 static nested class, non-static nested class, local class, anonymous class 입니다. 이 중에서 non static nested class가 inner class 입니다.

 

Inner class는 outer class(외부 클래스) 안에 선언되어 있는 클래스 입니다. 

class OuterClass {
   class InnerClass {};
}

이렇게 클래스 안에 자리 잡고 있는 클래스입니다. 하나의 class 안에 변수나 메서드를 정의하는 위치에 inner class를 정의하는 것입니다.

Outer class와 inner class 간에 긴밀한 연결이 있을 때에 사용하게 됩니다. 어떤 예시가 적절할까 생각을 해보았는데, 여러 색상의 볼펜 리필을 끼워서 사용하는 펜을 생각해보면 어떨까 싶습니다. 

출처: https://www.globalinterpark.com/detail/detail?prdNo=7851760496&dispNo=001850101006011

Outer class가 볼펜 케이스이고 inner class가 리필심 인것이죠!

리필심 자체는 크게 사용성이 없고 홀더와 같이 쓰여야만 하는 관계입니다. Outer class와 inner class의 관계도 이와 유사한 것 같습니다. 

Inner class를 initialize 할 때는 반드시 outer class의 instance를 통해서만 가능합니다.

어떤 말인지 한 번 예시를 보겠습니다. 아래 예제에 Pen과 그 안에 inner class로 Refill 클래스를 만들어 주었습니다.

Inner class는 outer class의 모든 methods나 fields에도 접근할 수가 있습니다.  private keyword가 붙은 멤버도 접근이 가능합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MultiColorPen {
    private ArrayList<Refill> refills;
    private String nameOfPen;
    private int numberOfColour;
 
    public MultiColorPen(String nameOfPen, int numberOfColour) {
        this.nameOfPen = nameOfPen;
        this.numberOfColour = numberOfColour;
    }
 
    //public으로 생성한 inner class
    public class Refill {
        private String color;
        private double amountOfInk;
        private double ballTipSize;
 
        public Refill(String color, double amountOfInk, double ballTipSize) {
            this.color = color;
            this.amountOfInk = amountOfInk;
            this.ballTipSize = ballTipSize;
        }
    }
}
cs

이제 Main class에서 각각 instance를 만들어 보겠습니다.

 

1
2
3
4
 MultiColorPen multiColorPen = new MultiColorPen("MyPen"3);
 
 //inner class instance 만들기
 MultiColorPen.Refill refill1 = multiColorPen.new Refill("Pink"10.00.3);
cs

Outer class인 MultiColorPen의 인스턴스는 일반적인 클래스의 인스턴스를 만들듯이 해주면 됩니다.

그렇지만 inner class인 Refill의 선언과 인스턴스 생성은 line#4에서 처럼 Outerclass.Innerclass의 형태로 타입을 잡아주고, 인스턴스를 만들때도 OuterClassInstance.new InnerClass(); 의 형태로 해주어야 합니다. 생소한 형태이지만 이런식으로 outer class의 instance를 통해서만 생성이 가능합니다.

 

*글 시작부에서 Inner class의 다른 이름이 non static nested class 였던 것 기억나시나요? 왜 non static인 걸까요?
바로 inner class의 인스턴스는 outer class의 인스턴스 안에서만 존재하기 때문입니다. static 멤버들은 프로그램이 시작함과 동시에 실행이 된다는 특성이 있는데, inner class의 경우 outer class의 영향을 받는 존재이기 때문에 static keyword를 사용하지 않도록 한 것입니다. (outer class의 인스턴스가 생성되기 전에 inner class의 멤버들이 활성화 된다면 맞지 않기 때문이죠.) 

MultiColorPen.Refill refill1 = multiColorPen.new Refill("Pink", 10.0, 0.3); 에서처럼 inner class는 outer class의 instance에 의존해서 생성된다는 점을 생각하면 왜 non static이어야 하는지 이해가 잘 될 것 같아 이야기해보았습니다. 
참고자료: https://www.quora.com/Why-can%E2%80%99t-inner-class-methods-be-static-in-Java

 

하지만 이렇게 inner class를 만들어 주는 방법은 외부에서 class의 내용에 접근한다는 점에서 encapsulation(캡슐화)이 이루어지지 않았다는 느낌이 들지 않으시나요? 캡슐화를 이루기 위해서는 어떻게 할 수 있을까요? 

바로 inner class의 접근제어자를 public에서 private으로 바꾸어 주면 됩니다. 이전에 캡슐화에서 fields의 접근 제어자를 private으로 바꾸었던 것과 동일합니다. 하지만 이렇게 갑자기 private으로 바꾸면 기존에 작성해 둔 코드에 에러가 발생하게 됩니다. 에러를 없애기 위해서 동일한 기능을 하는 method를 outer class에 만들어 주면 되겠죠?💪

 

1
2
3
public void addRefill(String color, double ballTipSize) {
        this.refills.add(new Refill(color,ballTipSize));
    }
cs

 

Refill class의 인스턴스를 만들어서 바로 refills array list에 add해 주는 method를 만들었습니다. 이렇게 하면 좀 전에 외부에서 Refill에 접근하여 인스턴스를 만드는 것과 같은 동작을 하면서도 Refill 인스턴스를 모아 두는 array list에도 데이터를 넣을 수 있게 되었습니다. 

 

1
2
3
MultiColorPen multiColorPen = new MultiColorPen("MyPen"3);
 
multiColorPen.addRefill("Black"0.3);
cs

 

이렇게 하면 Refill class를 private하게 유지하면서 인스턴스를 생성할 수 있게 되었습니다.

 

만약에 MultiColorPen 클래스의 인스턴스를 만들 때 자동으로 Black color, 0.3 size 리필이 추가되게 하고 싶다면 어떻게 할 수 있을까요? 이때도 addRefill을 사용할 수 있는데요, 바로 constructor 안에 넣는 것입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
    public MultiColorPen(String nameOfPen, int numberOfColour) {
        this.nameOfPen = nameOfPen;
        this.numberOfColour = numberOfColour;
        //Constructor 안에 addRefill method 사용
        for(int i = 0; i < numberOfColour; i++) {
            addRefill("Black"0.3);
        }
    }
 
    public void addRefill(String color, double ballTipSize) {
        this.refills.add(new Refill(color,ballTipSize));
    }
cs

 

검정색만 있는 다색 볼펜이라니 코드를 심플하게 하려다보니 따분한 볼펜이 되었지만 ㅎㅎ 이런 식으로 생성자 안에 함수를 호출하는 방법도 있다는 것을 알려드리고 싶었습니다. Array을 사용한다거나 하면 조금 더 다채롭게 할 수도 있을 것 같습니다. 

 

한 가지 추가적으로 알려드릴 것은 inner class는 외부 클래스의 인스턴스 변수나 클래스 변수에 접근할 수 있다는 사실인데요. private으로 정의되어 있는 변수여도 접근이 가능합니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MultiColorPen {
 
    //...
    private int numberOfColour;
 
    //...
 
    //public으로 생성한 inner class
    public class Refill {
        //...
 
        public void getNameOfPen() {
            //외부 class의 private 인스턴스 변수 값에 접근 가능
            System.out.println(nameOfPen);        
 
        }
    }
}
 
cs

 

여기까지가 inner class에 대한 간략한 내용이었습니다. 다음번에는 nested class의 다른 종류인 local class와 anonymous class에 대해서 알아보겠습니다.

감사합니다.☺️

 

 

https://www.geeksforgeeks.org/difference-between-static-and-non-static-nested-class-in-java/

 

Difference Between Static and Non Static Nested Class in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

 

Nested Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

반응형

'Java' 카테고리의 다른 글

Inner Class - Anonymous class(익명 클래스)  (0) 2022.05.10
Inner class - local class  (0) 2022.05.09
Interface(인터페이스) 알아보기(1)  (0) 2022.05.07
Autoboxing & Unboxing  (2) 2022.05.05
Array-배열  (0) 2022.05.02