Java Inner Class (내부 클래스)


자바 이너 클래스 혹은 중첩 클래스는 하나의 클래스로, 클래스나 인터페이스 내부에서 선언합니다. 

코드를 더 읽기 쉽고, 더 오래 유지 하기 위해, 논리적인 그룹과 인터페이스들에서 이너클래스를 사용합니다.

추가로, 이너클래스는 개인적인 데이터 멤버와 메소드를 포함하는 외부 클래스의 모든 멤버들에 접근할 수 있습니다.





syntax of Inner class



class Java_Outer_class{

//code

class Java_Inner_class{

//code

}




자바 이너 클래스의 이점


이너클래스에는 3가지 기본적인 이점이 있습니다. 


1) 중첩 클래스는 개인적인 것을 포함하는 외부 클래스의 모든 멤버(데이터 멤버와 메소드등)에 접근할 수 있다는 관련성의 특별한 타입을 나타냅니다.


2) 중첩 클래스는 논리 그룹 클래스와 인터페이스 내부에 있기 때문에 더 읽기 쉽고, 유지 가능한 코드 개발에 사용됩니다. 


3) 코드 최적화 : 작성하는데 더 적은 코드가 요구됩니다.





Difference between nested class and inner class in java

이너 클래스와 중첩 클래스의 차이


Inner클래스(내부클래스)는 중첩 클래스의 한 부분입니다.

여기서 정적 중첩 클래스는 이너클래스로 알려져 있습니다.



중첩 클래스의 2가지 타입


중첩 클래스에는 2가지 타입이 있습니다. 정적 중첩 클래스와 동적 중첩클래스가 있습니다.

여기서 정적 중첩 클래스는 이너클래스로 알려져 있습니다.


1. 정적 중첩 클래스 (이너 클래스)

 - 멤버 이너 클래스

 - 익명 이너 클래스

 - 지역 이너 클래스 


2. 동적 중첩 클래스 



TYPE 

Description 

Member Inner Class

클래스는 클래스와 외부 메소드 내에서 만들어집니다.

Anonymous Inner Class

클래스는 수행되는 인터페이스나 확장되는 클래스에 의해 만들어집니다. 

이름은 자바 컴파일러에 의해 결정됩니다. 

Local Inner Class

클래스는 메소드 내에서 만들어집니다.

Static Nested Class

중첩클래스는 클래스 내에서 만들어 집니다

Nested Class

인터페이스는 클래스나 인터페이스 내에서 만들어집니다.












1. Member inner class


정적 중첩 클래스는 클래스 내에서 만들어 지고, 외부 메소드는 멤버 이너 클래스라고 불립니다.


syntax:



class Outer{

//code

class Inner{

//code

}

}






Member inner class 의 예시


아래 예에서는, 

외부 클래스의 개인적 데이터 멤버로 접속 할 수 있는, 멤버 이너 클래스로 msg() 메소드를 만들 수 있습니다.





class TestMemberOuter1{

 private int data=30;

 class Inner{

  void msg(){System.out.println("data is "+data);}

}

 public static void main(String args[]){

  TestMemberOuter1 obj=new TestMemberOuter1();

  TestMemberOuter1.Inner in=obj.new Inner();

  in.msg();

 }


output

data is 30 




자바 멤버 이너 클래스의 내부 동작


자바 컴파일러는 이너 클래스의 케이스 안에 2개의 클래스 파일을 만듭니다.

이너 클래스의 클래스 파일 이름은 "Outer$Inner" 입니다.

만약 이너클래스를 생성하길 원한다면, 외부 클래스의 인스턴스를 만들어야 합니다. 

그런 경우, 외부 클래스의 인스턴스 안에 이너 클래스의 인스턴스가 만들어 집니다. 



컴파일러에 의한 내부 코드 발생


자바 컴파일러는 "Outer$Inner"라 이름 지어진 클래스 파일을 만듭니다.

멤버 이너 클래스는 외부 클래스의 참조를 가집니다. 

때문에 개인적인 것을 포함하여 외부 클래스의 모든 데이터 멤버에 접속 할 수 있습니다.




import java.io.PrintStream;

class Outer$Inner

{

     final Outer this$0;

     Outer$Inner()

     {   super();

         this$0 = Outer.this;

      }

      void msg()

      { 

          System.out.println((new StringBuilder()).append("data is ")

                        .append(Outer.access$000(Outer.this)).toString());

      }

} 















2. Anonymous inner class


 이 클래스는 이름이 없는 익명 이너 클래스로 알려져 있습니다.

당신이 인터페이스나 클래스의 메소드를 오버라디으 해야만 한다면, 이 클래스가 사용될 수 있습니다.

자바 익명 클래스는 2가지 방법으로 만들 수 있습니다


1. 클래스 ( 추상적 혹은 실제적 )

2. 인터페이스 




1- 클래스를 사용하는 익명 inner class 의 예시




abstract class Person{

   abstract void eat();

 }

class TestAnonymousInner{

 public static void main(String args[]){

  Person p=new Person(){

  void eat(){System.out.println("nice fruits");}

  };

  p.eat();

 }

}


output

nice fruits





1-주어진 코드의 내부 동작



Person p=new Person(){

  void eat(){System.out.println("nice fruits");}

  };



1. 클래스는 생성되지만 이름은 확장한 person 클래스 컴파일러에 의해 결정되고, eat() 메소드를 구동시킵니다.


2. 익명 클래스의 한 객체는 Person 타입의 기본설정변수와 참조와 관련되어 만들어 집니다. 




1-컴파일러에 의한 내부 코드 발생



import java.io.PrintStream;

 static class TestAnonymousInner$1 extends Person

{

     TestAnonymousInner$1(){}

     void eat()

       {

           System.out.println("nice fruits");

        }

}







2-인터페이스를 사용하는 익명 inner class 의 예시




interface Eatable{

  void eat();

}

class TestAnnonymousInner1{

  public static void main(String args[]){

  Eatable e=new Eatable(){

    public void eat(){System.out.println("nice fruits");}

 };

 e.eat();

 }

}



output

nice fruits



2-주어진 코드의 내부 동작


이 코드에서는 2개의 메인 작업을 수행합니다.




Eatable p=new Eatable(){

void eat(){System.out.println("nice fruits");}

};



1. 클래스는 생성되지만 이름은 식용가능한 인터페이스 구동 컴파일러에 의해 결정되고, eat() 메소드를 구동시킵니다.


2. 익명 클래스의 한 객체는 식용가능 타입의 기본설정변수와 참조와 관련되어 만들어 집니다. 





2-컴파일러에 의한 내부 코드 발생



import java.io.PrintStream;

 static class TestAnonymousInner$1 implements Eatable

{

     TestAnonymousInner$1(){}

     void eat(){System.out.println("nice fruits");}

}














3. Local inner class


메소드 안에서 생성되는 클래스를 지역 이너 클래스라 부릅니다.

만약 지역 이너 클래스를 불러오고 싶다면, 메소드 안에 클래스를 만들어야 합니다.





지역 inner class 의 예시



public class localInner1{

    private int data=30; // 인스턴스 변수

    void display(){

      class Local{

        void msg(){System.out.println(data);}

     }

    Local l=new Local();

     l.msg();

     }

     public static void main(String args[]){

       localInner1 obj=new localInner1();

        obj.display();

   }

}


output

30




컴파일러에 의한 내부 코드 발생


컴파일러는 외부 클래스의 참조를 가지는 클래스 Simple$1Local 를 만듭니다.




import java.io.PrintStream;

class localInner1$Local

 {

     final localInner1 this$0;

     localInner1$Local()

     {

         super();

         this$0 = Simple.this;

     }

     void msg()

     {

         System.out.println(localInner1.access$000(localInner1.this));

     }

 }



규칙 : 지역 변수는 개인적, 공용 혹은 보호를 할 수 없습니다.



지역 이너 클래스의 규칙


지역 이너 로컬 클래스는 외부 메소드로부터 불러올 수 없습니다.

지역 이너 로컬 클래스는 JDK 1.7까지는 마지막이 아닌 지역 변수에 접속할 수 없습니다.

JDK 1.8부터, 지역 이너 클래스의 마지막이 아닌 지역 변수에 접속 할 수 있습니다.



Example of local inner class with local variable


지역 변수가 적용된 지역 이너 클래스의 예시



class localInner2{

 private int data=30; //인스턴스 변수

 void display(){

  int value=50; //지역 변수는 JDK 1.7까지는 마지막이어야 한다.

  class Local{

   void msg(){System.out.println(value);}

  }

  Local l=new Local();

  l.msg();

 }

 public static void main(String args[]){

  localInner2 obj=new localInner2();

   obj.display();

 }

}


output

50










4. static nested inner class

이 클래스는 정적 중첩 클래스라고 불리는 클래스 안에서 만들어 집니다. 
그리고 동적 데이타 맴버와 메소드에는 접속할 수 없습니다.
또한 외부 클래스 네임에 의해 접속될 수 있습니다.

 1- private을 포함하는 외부 클래스의 정적 데이터 멤버에 접속 할 수 있습니다.
 2- 정적 중첩 클래스는 동적 데이터 멤버나 메소드에 접속할 수 없습니다.



인스턴스 메소드와 자바 정적 중첩 클래스의 예시


class TestOuter1{

  static int data=30;

  static class Inner{

   void msg(){System.out.println("data is "+data);}

  }

  public static void main(String args[]){

  TestOuter1.Inner obj=new TestOuter1.Inner();

  obj.msg();

  }

}


output

date is 30



위의 예에서, 여러분은 정적 중첩 클래스의 인스턴스를 만들 필요가 있습니다. 왜냐하면 그 클래스는 인스턴스 메소드 msg()를 가지기 때문입니다. 
하지만 여러분이 중첩 클래스가 정적이고 정적특성이라서 외부 클래스의 객체를 만들 필요가 없다면, 메소드나 클래스는 객체 없이 접근 할 수 있습니다. 


컴파일러에 의한 내부 코드 발생


import java.io.PrintStream;

static class TestOuter1$Inner

{

TestOuter1$Inner(){}

void msg(){

System.out.println((new StringBuilder()).append("data is ")

.append(TestOuter1.data).toString());

}

}




자바 정적 중첩 클래스 예시와 정적 메소드


만약 정적 중첩 클래스 안에 정적 멤버를 가진다면, 정적 중첩 클래스의 인스턴스를 만들 필요가 없습니다.



class TestOuter2{

   static int data=30;

   static class Inner{

    static void msg(){System.out.println("data is "+data);}

  }

  public static void main(String args[]){

  TestOuter2.Inner.msg(); //정적 중첩 클래스의 인스턴스를 만들 필요가 없습니다.

  }

}


output

date is 30











5. Nested interface


다른 인터페이스나 클래스에서 선언된 인터페이스는 중첩 인터페이스라 불립니다.
중첩 인터페이스는 유지를 쉽게 하기 위해 인터페이스와 관계된 그룹에 사용됩니다.
중첩 인터페이스는 외부 인터페이스나 클래스에 의해 적용되어야 합니다. 
또한 다이렉트로 접근 할 수 없습니다. 

 - 중첩 인터페이스를 기억하기 위한 포인트.
 
  자바 프로그래머가 기억해야 할 만한 몇 가지 포인트가 있습니다.

1- 만약 인터페이스 내에 선언된다면, 중접 인터페이스를 공개해야 하고, 클래스 내에 선언된다면, 액세스 수정을 할 수 있습니다. 

2- 중첩 인터페이스는 정적으로 선언됩니다.


인터페이스 내에 선언된 중첩 인터페이스 구문


interface interface_name{

...

interface nested_interface_name{

...

}





클래스 내에 선언된 중첩 인터페이스 구문


class class_name{

...

interface nested_interface_name{

...

}

}






인터페이스 내에 선언된 중첩 인터페이스의 예


interface Showable{

   void show();

   interface Message{

    void msg();

   }

}


class TestNestedInterface1 implements Showable.Message{

 public void msg(){System.out.println("Hello nested interface");}

 public static void main(String args[]){

  Showable.Message message=new TestNestedInterface1(); //upcasting here

  message.msg();

 }

}  













영어원문내용출처 :http://www.javatpoint.com/

번역,의역 및 작성 : 초코토끼

검수 : 개발토끼

오역 및 오타의 지적은 겸손히 받겠습니다.





+ Recent posts