파파비의 블로그

중첩클래스 (일반 중첩클래스, Static 중첩클래스, 메소드 중첩 클래스, 익명 중첩클래스) 본문

개발/java

중첩클래스 (일반 중첩클래스, Static 중첩클래스, 메소드 중첩 클래스, 익명 중첩클래스)

N. Dave 2020. 4. 4. 17:51
반응형

보통 클래스를 만들 때는 새로 파일을 만들어서 거기에 class 내용을 넣는다.

이런 과정이 어떻게 보면 불편할 수도 있다. 특히 새로 만들어서 한 번만 쓸 경우에는 굳이 파일까지 만들어서

하는 과정이 많이 번거롭게 느껴질 수 있다. 그럴 때는 중첩클래스의 개념을 한 번 활용해 보는게 어떨까?

 

중첩클래스에는 4가지가 대표적으로 있다.

 

1. 가장 일반적인 형태로 class안에 class를 만드는 일반 중첩 클래스

2. class안에 class를 만드는데, static class로 만드는 static 중첩 클래스

3. 메소드 안에 클래스를 만들어서 메소드 안에서만 쓰는 메소드 중첩 클래스 

4. 한 번만 오버로딩해서 쓸, 익명중첩클래스가 있다.

 

디테일한 내용을 한 번 알아보도록 하자.

 

1) 일반 중첩 클래스

 - class 안에 또 다른 class를 만들어서 사용하는 방법이다.

 - 특징 : inner class를 구현할 때는 outer class에 대한 멤버들을 참고할 수 있다.

 - 그러나,  outer class의 멤버들은 inner class에 대한 내용들에 접근할 수 없다

   <이유를 생각해보자>

     : inner class도 어찌됐든 class이긴 하다. class의 멤버들을 사용하려면 객체가 있어야 하는데, 객체를 구현하기 전에는 사용할 수 없기 때문에, outerclass에서 객체를 통하지 않고 곧 바로 접근하는 것이 안되는 것은 당연하다. 예를 들면, inner class에 int멤버가 있다면 여기에 접근하려면 객체를 통해서 해야하고, outer class에서 객체를 거치지 않고 접근할 수는 없다.

 - 구현방법은 outer class의 멤버이므로, outer class의 객체를 통해 접근해야 한다. 명명하는 방법이 조금 특이하니 손으로 꼭 여러 번 구현해봐야 헷갈리지 않을 것 같다.

class OuterClass{

    class InnerClass{

 

   }

}

이렇게 존재하는 InnerClass객체를 구현하는 방법은 다음과 같다.

 

//먼저 outer class 객체를 만든다.

OuterClass out = new OuterClass();

 

// outer class를 통해 inner class의 new + 생성자를 호출한다.

OuterClass.InnerClass InstanceName = out.new InnerClass();

 

개인적으로는 Class 이름을 호출 할 때도 outerclass에 점을 붙이는 부분과

new키워드를 객체에서 .을 찍고 쓴다는 부분이 특이하게 느껴졌다.

 

접근제한자는 용도에 따라 잘 활용하면 될 것 같다.

연습해볼 때는 한 페이지 안에 따로 추가적으로 중첩클래스를 만들어서 public을 굳이 사용할 필요는 없었다.

 

 

 

2) static 중첩클래스

 

 - 클래스 안에 클래스를 구현하는데 static을 붙이는 형태이다.

 - 그냥 일반 static 멤버들을 생각해보라, 객체를 만들어서 접근할 필요가 없다! 따라서 static 중첩클래스 또한 outer class의 static 멤버로서 따로 outerclass의 객체를 구현해서 접근할 필요가 없다. 이것이 일반 중첩클래스와 다른 점이다.

 - 그래서 파생되는 또 다른 점은, inner class는 outer class의 static 멤버만 곧장 접근가능하고, 다른 멤버들은 객체를 따로 구현해서 접근해야 한다. 일반 중첩은 당연히 outer class의 객체를 구현해야 하니, inner class는 자유롭게 멤버들에 접근가능했지만 static인 이상 그렇지 않다.

 

 - 구현하는 방법은 일반 중첩클래스와 약간 다르다. 일반중첩클래스에 대한 이해와, static의 개념에 대해 잘 이해했다면 그렇게 어렵지는 않을 것이다.

 

class OuterClass{

    static class InnerClass{

    }

}

이런 static 중첩 클래스가 있다고 생각해보자.

InnerClass의 객체는 다음과 같이 생성한다.

 

//OuterClass의 객체를 만들 필요가 없지 바로 접근한다.

OuterClass.InnerClass InstanceName = new OuterClass.InnerClass();

 

평소 새로운 객체 만드는 형식과 거의 비슷하다.

 

 

 

3. 메소드 중첩메소드

- 메소드 안에서 클래스를 만들고 해당 메소드 안에서만 사용하는 것이다.

- 메소드 안에서 만들고 다른 곳에서 만들 수는 없을까? 아쉽지만 그럴 수 없다.

  <이유를 생각해보자> (참고 : https://aljjabaegi.tistory.com/387)

  : 메소드랑 클래스는 메모리에 올려지는 방식이 다르다. 깊게 이해하고 싶으면 위에 참고 링크를 들어가서 잘 읽어보면 도움이 될 것이다!

  : 메소드는 실행이 되면 메모리에 올려진다. 그리고 사용이 다 되면 사라진다. 그렇기 때문에 메소드 밖에서는 구현된 메소드 중첩 클래스를 사용할 수 없다. 왜냐하면 실행 당시에는 메모리에 없을 것이기 때문이다.

  : 반대로 메소드 중첩 클래스는 outer class의 객체 생성없이 접근은 static 멤버중에서 final static 멤버에게만 접근가능하다. 이유는 확실하진 않지만, out class의 멤버들의 경우 변경이 가능하기 때문에 개발자 입장에서는 코드 구현에 있어서 리스크가 존재할 것이라서 막아둔 것이 아닐까 예측해 본다. 그외에는 그냥 outer 객체를 만들어서 접근하는 것은 가능하다.

 

 - 구현 방법을 한번 살펴보자. 

 

class OuterClass{

   public static void main(String[] args){

      // 메소드 내에 class를 만들었다.

      class InnerClass{

           void sayHi(){ System.out.println("Hi"); }

       }

 

      // 객체 구현은 쉽다. 바로 메소드 내에서 구현한다.

      InnerClass InstanceName = new InnerClass();

      InstanceName.sayHi(); // 잘 실행될 것이다.

   }

}

구현 방법은 이렇다. 

 

class OuterClass{

   int num1 = 1;

   static int num2 = 2;

   final static int num3 = 3; 

 

   public static void main(String[] args){

      // 메소드 내에 class를 만들었다.

      class InnerClass{

           void sayHi()

         { System.out.println(num1); // static 멤버가 아니기에 오류. OuterClass 객체를 만들어서 객체에서 접근한다. 

           System.out.println(num2); // static이지만 final이 아니다. 따라서 오류.

           System.out.println(num3); // 가능

         } 

     }

   }

}

inner class에 대한 outer class 멤버 접근에 대한 포인트는 위와 같다.

 

 

 

4. 익명클래스

- 익명클래스는 상속을 진행한 클래스인데 이름이 없기 때문에 익명클래스라고 불린다.

- 이름이 없다니? 이름을 짓지도 않고 바로 상속을 진행하고(오버라이딩 등등) 그리고 바로 써버리기 때문에 이름이 필요 없다.

- 한번 구현된 코드를 보자.

 

class program{

   public void staic main(String[] args){

      

        Animal animal = new Animal(){

            public void Sound(){

            System.out.println("New Sound");

            }

        

        animal.Sound();

};

 

}

 

 

Class Animal{

   public void Sound(){

           System.out.println("Animal Sound");    

       }

   }

}


위 코드를 실행하면 어떤 글자가 컨솔에 찍힐 것인가?

> 정답은 new sound 이다.

 

animal의 Animal class를 상속한 어떤 익명의 클래스 객체이다. 그리고 그 클래스는 sound라는 메소드를 오버라이딩 했다. 

 

익명클래스는 왜 쓸까?

이렇게 매번 오버라이딩 해야하는 클래스가 존재하고, 경우에 따라 다양하게 오버라이딩해야하는 경우 매번 파일을 새로 만들어서 class를 만들면 너무 비효율적이다. 간단하게 몇줄 코드를 추가하면 파일을 만들지 않고 그 자리에서 바로 쓸 수 있다.

 

처음에 안드로이드 개발에서 코드를 봤는데 익명클래스에 대한 개념을 몰라서 안드로이드에서만 쓰이는 특이한 코드인줄 알았다.

 

자바 공부를 더욱 깊게 해야겠다.

 

 

반응형

'개발 > java' 카테고리의 다른 글

Thread 쓰레드  (0) 2020.04.05
인터페이스  (0) 2020.04.05
추상클래스, 추상메소드  (0) 2020.04.05
단락 평가, ||/|의 차이 그리고 &&/&의 차이  (0) 2020.04.01
난수를 만들어내는 방법, Random 객체  (0) 2020.04.01
Comments