Java의 내부 클래스와 익명 클래스에 대한 포괄적인 이해

자바 내부 클래스(Inner Class), 유사한 개념은 C++에도 있다. 바로 플러그인 클래스(Nested Class)이다. 언뜻 보기에는 내부가 약간 쓸데없는 것 같다. 그 용도는 초보자에게는 그리 현저하지 않을 수도 있지만, 그것에 대해 깊이 이해하면서 자바의 디자이너가 내부 클래스에 대해 확실히 고심하고 있다는 것을 알 수 있다.내부 클래스를 사용하는 것을 습득하는 것은 자바 고급 프로그래밍의 일부분으로 프로그램 구조를 더욱 우아하게 설계할 수 있다.다음은 다음과 같은 몇 가지 측면에서 설명합니다.
첫만남

public interface Contents {
  int value();
}

public interface Destination {
  String readLabel();
}

public class Goods {
  private class Content implements Contents {
    private int i = 11;
    public int value() {
      return i;
    }
  }

  protected class GDestination implements Destination {
    private String label;
    private GDestination(String whereTo) {
      label = whereTo;
    }
    public String readLabel() {
      return label;
    }
  }

  public Destination dest(String s) {
    return new GDestination(s);
  }
  public Contents cont() {
    return new Content();
  }
}

class TestGoods {
  public static void main(String[] args) {
    Goods p = new Goods();
    Contents c = p.cont();
    Destination d = p.dest("Beijing");
  }
}
이 예에서 클래스 콘텐츠와 GDestination은 클래스 Goods 내부에 정의되고 각각protected와private 수식자를 가지고 접근 단계를 제어합니다.콘텐츠는 Goods의 내용을 대표하고 GDestination은 Goods의 목적지를 대표한다.그것들은 각각 두 개의 인터페이스 Content와 Destination을 실현했다.뒤에 있는main 방법에서 Contents c와 Destination d로 직접 조작하면 이 두 내부 클래스의 이름도 볼 수 없습니다!이렇게 하면 내부류의 첫 번째 장점은 당신이 다른 사람에게 알리고 싶지 않은 조작, 즉 봉장성을 숨기는 것이다.
이 동시에 우리는 외부 클래스의 작용 범위 밖에서 내부 클래스의 대상을 얻는 첫 번째 방법을 발견했다. 그것이 바로 외부 클래스의 방법을 이용하여 창설하고 되돌아오는 것이다.상례의cont()와dest() 방법은 이렇게 하는 것입니다.그럼 다른 방법은 없을까요?물론 다음과 같은 문법 형식이 있습니다.

outerObject=new outerClass(Constructor Parameters);

outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);
비정적 내부 클래스 대상을 만들 때 반드시 상응하는 외부 클래스 대상을 먼저 만들어야 한다는 것을 주의하십시오.원인에 대해서도 우리의 다음 화제를 불러일으켰다.
비정적 내부 클래스 대상은 외부 클래스 대상을 가리키는 인용을 가지고 있다
방금 예제를 수정합니다.

public class Goods {

  private valueRate=2;

  private class Content implements Contents {
    private int i = 11*valueRate;
    public int value() {
      return i;
    }
  }

  protected class GDestination implements Destination {
    private String label;
    private GDestination(String whereTo) {
      label = whereTo;
    }
    public String readLabel() {
      return label;
    }
  }

  public Destination dest(String s) {
    return new GDestination(s);
  }
  public Contents cont() {
    return new Content();
  }
}
수정된 부분은 빨간색으로 표시됩니다.여기서 Goods 클래스에private 구성원 변수valueRate를 추가했습니다. 의미는 화물의 가치 계수입니다. 내부 클래스content의 방법value()가 가치를 계산할 때 그것을 곱합니다.우리는value()가valueRate에 접근할 수 있다는 것을 발견했다. 이것은 내부 클래스의 두 번째 장점이기도 하다. 즉, 내부 클래스 대상은 외부 클래스를 만드는 내용에 접근할 수 있고, 심지어는 개인 변수까지 포함한다.이것은 매우 유용한 특성으로 우리가 디자인할 때 더욱 많은 사고방식과 지름길을 제공하였다.이 기능을 실현하려면 내부 클래스 대상은 반드시 외부 클래스 대상을 가리키는 인용이 있어야 한다.자바 컴파일러는 내부 클래스 대상을 만들 때 외부 클래스 대상의 인용도 은밀하게 전달하고 저장합니다.이렇게 하면 내부 클래스 대상이 항상 외부 클래스 대상에 접근할 수 있고 외부 클래스의 작용 범위 밖에서 내부 클래스 대상을 만들려면 반드시 외부 클래스 대상을 먼저 만들어야 하는 이유이기도 하다.
내부 클래스의 한 구성원 변수가 외부 클래스의 한 구성원 변수와 동명이면 외부 클래스의 동명 구성원 변수가 차단되면 어떻게 합니까?괜찮습니다. Java에서는 외부 클래스에 대한 참조를 다음과 같이 표현합니다.

outerClass.this
그것이 있으면 우리는 이런 차단 상황을 두려워하지 않을 것이다.
정적 내부 클래스
일반적인 클래스와 마찬가지로 내부 클래스도 정태적일 수 있다.그러나 비정적 내부 클래스와 비교하면 정적 내부 클래스가 외부를 가리키는 인용이 없다는 데 차이가 있다.이것은 실제적으로 C++의 플러그인 클래스와 매우 비슷하다. 자바 내부 클래스와 C++ 플러그인 클래스의 가장 큰 차이는 외부를 가리키는 인용이 있는지에 있다. 물론 디자인의 측면과 그 세부 사항으로 볼 때 차이가 있다.
그 밖에 어떠한 비정적 내부 클래스에서도 정적 데이터, 정적 방법 또는 또 하나의 정적 내부 클래스(내부 클래스의 끼워넣기는 한 층이 아닐 수 있다)가 있을 수 없다.하지만 정적 내부 클래스에서는 이 모든 것을 가질 수 있다.이것도 양자의 두 번째 차이라고 할 수 있겠지.
부분 내부 클래스
예, Java 내부 클래스도 부분적일 수 있습니다. 이것은 하나의 방법, 심지어 코드 블록 안에 정의할 수 있습니다.

public class Goods1 {
   public Destination dest(String s) {
     class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
          label = whereTo;
        }
        public String readLabel() { return label; }
     }
     return new GDestination(s);
   }

   public static void main(String[] args) {
     Goods1 g= new Goods1();
     Destination d = g.dest("Beijing");
   }
}
위에서 바로 이런 예이다.방법dest에서 우리는 내부 클래스를 정의했고 마지막으로 이 방법으로 이 내부 클래스의 대상을 되돌려줍니다.만약 우리가 내부 클래스를 사용할 때 그것의 대상을 만들고 외부에 창조하기만 하면 이렇게 할 수 있다.물론 방법에 정의된 내부류는 디자인을 다양화할 수 있고 용도는 이 점에 그치지 않는다.
다음은 더 이상한 예가 하나 있다.

public class Goods2{
   private void internalTracking(boolean b) {
     if(b) {
        class TrackingSlip {
          private String id;
          TrackingSlip(String s) {
             id = s;
          }
          String getSlip() { return id; }
        }
        TrackingSlip ts = new TrackingSlip("slip");
        String s = ts.getSlip();
     }
   }

   public void track() { internalTracking(true); }

   public static void main(String[] args) {
     Goods2 g= new Goods2();
     g.track();
   }
}
이 내부 클래스의 대상을 if 외에 만들 수 없습니다. 왜냐하면 이것은 이미 그 역할 영역을 넘어섰기 때문입니다.그러나 컴파일할 때 내부 클래스 Tracking Slip은 다른 클래스와 마찬가지로 동시에 컴파일됩니다. 단지 그 자체의 작용 영역에 의해 이 범위를 초과하면 무효입니다. 그 외에 다른 내부 클래스와 차이가 없습니다.
익명 내부 클래스
자바의 익명 내부 클래스의 문법 규칙은 보기에는 좀 이상해 보이지만, 익명 그룹처럼 하나의 클래스의 대상을 만들고 이름을 사용할 수 없을 때, 내부 클래스를 사용하면 코드를 간결하고 명확하게 보일 수 있다.문법 규칙은 다음과 같습니다.

new interfacename(){......};   new superclassname(){......};
다음은 앞에서 예를 들어 보겠습니다.

public class Goods3 {
   public Contents cont(){
     return new Contents(){
        private int i = 11;
        public int value() {
          return i;
        }
     };
   }
}
이 방법cont()는 익명 내부 클래스를 사용하여 인터페이스 Contents를 실현한 클래스의 대상을 직접 되돌려줍니다. 보기에 매우 간결합니다.
자바의 이벤트 처리 익명 어댑터에서 익명 내부 클래스가 대량으로 사용됩니다.예를 들어 창을 닫으려면 다음과 같은 코드를 추가합니다.

frame.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent e){
     System.exit(0);
   }
});
한 가지 주의해야 할 것은 익명 내부 클래스는 이름이 없기 때문에 구조 함수가 없다는 것이다. (그러나 이 익명 내부 클래스가 파라미터만 있는 구조 함수를 포함하는 부류를 계승한다면 이를 만들 때 반드시 이 파라미터를 가지고 실현되는 과정에서 슈퍼 키워드를 사용하여 해당하는 내용을 호출해야 한다.)구성원 변수를 초기화하려면 다음과 같은 몇 가지 방법이 있습니다.
만약 한 방법의 익명 내부 클래스라면, 이 방법을 이용하여 당신이 원하는 매개 변수를 전달할 수 있지만, 이 매개 변수들은final로 성명되어야 한다는 것을 기억하십시오.
익명 내부 클래스를 이름이 있는 국부 내부 클래스로 바꾸면 구조 함수를 가질 수 있다.
이 익명 내부 클래스에서 초기화 코드 블록을 사용합니다.
왜 내부 클래스가 필요합니까?
java 내부 클래스는 어떤 장점이 있습니까?왜 내부 클래스가 필요합니까?
먼저 간단한 예를 들어 만약에 당신이 인터페이스를 실현하고 싶지만 이 인터페이스의 한 방법은 당신이 구상한 이 종류의 한 방법의 명칭과 파라미터가 같으면 어떻게 해야 합니까?이때 너는 내부 클래스를 만들어서 이 인터페이스를 실현할 수 있다.내부 클래스는 외부 클래스의 모든 내용에 접근할 수 있기 때문에 이렇게 하면 당신이 직접 이 인터페이스를 실현하는 모든 기능을 완성할 수 있습니다.
하지만 의문을 제기해야 할 것 같아. 방법을 바꾸면 되지 않겠어?
확실히 이를 디자인 내부류로 삼는 이유는 설득력이 없다.
진정한 원인은 이렇다. 자바의 내부 클래스와 인터페이스를 합치면 C++ 프로그래머들이 자바에 존재하는 문제점 중 하나가 상속이 많지 않다고 불평하는 것을 해결할 수 있다.실제로 C++의 다중 계승 디자인은 매우 복잡하지만 자바는 내부 클래스에 인터페이스를 추가하여 다중 계승 효과를 잘 실현할 수 있다.
java 내부 클래스 총결산
(1) 메서드 간에 정의된 비정적 내부 클래스:
● 외곽류와 내부류는 서로 자신의 개인 구성원을 방문할 수 있다.
● 내부 클래스에서는 정적 구성원 변수를 정의할 수 없습니다.
외부 클래스 작용 범위의 외향에서 내부 클래스 대상을 만들려면 먼저 외부 클래스 대상을 만들어야 한다
(2) 메서드 간에 정의된 정적 내부 클래스:
● 외부 클래스에만 접근할 수 있는 정적 구성원.
정적 내부 클래스가 외부를 가리키는 인용이 없습니다
(3) 메서드에 정의된 로컬 내부 클래스:
● 이 내부 클래스는 접근 제어 권한이 없습니다
● 외곽류는 방법 중의 국부 내부류는 보이지 않지만 국부 내부류는 외곽류의 모든 구성원에게 접근할 수 있다.
● 방법체에서는 국부 내부 클래스에 접근할 수 있지만 방문 문장은 국부 내부 클래스를 정의한 후에 접근해야 한다.
● 국부 내부 클래스는 방법체의 상량, 즉final로 장식된 구성원에게만 접근할 수 있다.
(4) 메서드에 정의된 익명 내부 클래스:
● 구조기가 없는 대신 구조기 파라미터를 초유형 구조기에 전달
하나의 클래스를 만들 수 있을 뿐만 아니라 이름을 사용할 수 없을 때, 익명 내부 클래스를 사용하면 코드를 간단명료하게 보일 수 있습니다.
자바의 내부 클래스와 익명 클래스를 전면적으로 이해하는 이 편은 여러분께 공유한 모든 내용입니다. 참고 부탁드리며 많은 응원 부탁드립니다.

좋은 웹페이지 즐겨찾기