자바 향상 편 (9) - 익명 내부 클래스 상세 설명

본문http://blog.csdn.net/chenssy/article/details/13170015
       자바 향상 편 - 내부 류 에서 익명 내부 류 에 대해 간단 한 소 개 를 했 지만 내부 류 에 다른 세부 적 인 문제 가 많이 존재 하기 때문에 이 블 로 그 를 파생 시 켰 다.이 블 로그 에 서 는 익명 내부 류 의 사용, 익명 내부 류 가 주의해 야 할 사항, 익명 내부 류 를 어떻게 초기 화 하 는 지, 익명 내부 류 가 사용 하 는 형 삼 이 왜 final 인지 알 수 있다.
       1. 익명 내부 클래스 사용
       익명 내부 클래스 는 이름 이 없어 서 생 성 방식 이 좀 이상 합 니 다.생 성 형식 은 다음 과 같 습 니 다:
new      (    )|    ()  
    {  
     //            
    }

       여기 서 우 리 는 익명 의 내부 류 를 사용 하 는 것 을 보 았 다. 우 리 는 하나의 부모 류 를 계승 하거나 하나의 인 터 페 이 스 를 실현 해 야 한다. 물론 하나의 부모 류 만 계승 하거나 하나의 인 터 페 이 스 를 실현 할 수 있다.또한 클 라 스 키워드 도 없습니다. 익명 내부 클래스 는 new 를 직접 사용 하여 대상 의 인용 을 만 들 기 때 문 입 니 다.물론 이 인용 은 암시 적 이다.
public abstract class Bird {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public abstract int fly();
}

public class Test {
    
    public void test(Bird bird){
        System.out.println(bird.getName() + "    " + bird.fly() + " ");
    }
    
    public static void main(String[] args) {
        Test test = new Test();
        test.test(new Bird() {
            
            public int fly() {
                return 10000;
            }
            
            public String getName() {
                return "  ";
            }
        });
    }
}
------------------
Output:
      10000 

       Test 류 에서 test () 방법 은 Bird 유형의 인 자 를 받 아들 이 는 동시에 우 리 는 추상 류 가 직접적 으로 new 할 수 없다 는 것 을 알 고 있다. 우 리 는 먼저 실현 류 가 있어 야 new 가 그의 실현 사례 를 나 올 수 있다.그래서 mian 방법 에서 익명 내부 클래스 를 직접 사용 하여 Bird 인 스 턴 스 를 만 듭 니 다.
       익명 내부 류 는 추상 류 가 될 수 없 기 때문에 추상 적 인 부류 나 인터페이스 안의 모든 추상 적 인 방법 을 실현 해 야 한다.
       이 익명 내부 코드 는 다음 과 같은 형식 으로 나 눌 수 있 습 니 다.
public class WildGoose extends Bird{
    public int fly() {
        return 10000;
    }
    
    public String getName() {
        return "  ";
    }
}

WildGoose wildGoose = new WildGoose();
test.test(wildGoose);

       이 시스템 에 서 는 Bird 류 의 익명 류 를 계승 하 는 대상 을 만 들 고 이 대상 은 Bird 유형 에 대한 참조 로 전환 합 니 다.
       익명 내부 클래스 의 사용 에 결함 이 있 습 니 다. 한 번 만 사용 할 수 있 고 익명 내부 클래스 를 만 들 때 바로 이러한 인 스 턴 스 를 만 듭 니 다. 이러한 정 의 는 바로 사라 지기 때문에 익명 내부 클래스 는 중복 사용 할 수 없습니다.위의 인 스 턴 스 에 대해 서 는 test () 방법 에서 내부 류 를 여러 번 사용 해 야 한다 면 익명 내부 류 를 사용 하 는 것 이 아니 라 클래스 를 다시 정의 하 는 것 을 권장 합 니 다.
       주의사항
       익명 내부 클래스 를 사용 하 는 과정 에서 우 리 는 다음 과 같은 몇 가 지 를 주의해 야 한다.
      1. 익명 내부 유형 을 사용 할 때 우 리 는 하나의 유형 을 계승 하거나 하나의 인 터 페 이 스 를 실현 해 야 한다. 그러나 둘 다 얻 을 수 없 는 동시에 하나의 유형 을 계승 하거나 하나의 인 터 페 이 스 를 실현 할 수 밖 에 없다.
      2. 익명 내부 클래스 에서 구조 함 수 를 정의 할 수 없습니다.
      3. 익명 내부 클래스 에 정적 구성원 변수 와 정적 방법 이 존재 할 수 없습니다.
      4. 익명 내부 류 는 국부 내부 류 이기 때문에 국부 내부 류 의 모든 제한 은 익명 내부 류 에 도 효력 이 발생 한다.
      5. 익명 의 내부 유형 은 추상 적 인 것 이 아니 라 계승 하 는 유형 이나 실현 하 는 인터페이스의 모든 추상 적 인 방법 을 실현 해 야 한다.
       3. 사용 하 는 형 삼 은 왜 final 입 니까?
       참고 파일:http://android.blog.51cto.com/268543/384844
       우리 가 익명 의 내부 클래스 에 파 라 메 터 를 전달 할 때 이 인삼 이 내부 클래스 에서 사용 되 어야 한다 면 이 인삼 은 final 이 어야 합 니 다.즉, 소재 하 는 방법의 형 삼 이 내부 류 에서 사용 되 어야 할 때 이 형 삼 은 반드시 final 이 어야 한 다 는 것 이다.
      왜 final 이 어야 합 니까?
      우선 내부 클래스 컴 파일 에 성공 하면 class 파일 이 생 성 된다 는 것 을 알 고 있 습 니 다. 이 class 파일 은 외부 클래스 와 같은 class 파일 이 아니 라 외부 클래스 에 대한 참조 만 유지 합 니 다.외부 클래스 에서 들 어 오 는 인자 가 내부 클래스 로 호출 되 어야 할 때 자바 프로그램의 측면 에서 볼 때 직접 호출 됩 니 다.
public class OuterClass {
    public void display(final String name,String age){
        class InnerClass{
            void display(){
                System.out.println(name);
            }
        }
    }
}

      위의 코드 에서 보면 name 매개 변 수 는 내부 클래스 에 의 해 직접 호출 되 어야 하 는 것 같 습 니 다.그렇지 않 습 니 다. 자바 컴 파일 후 실제 작업 은 다음 과 같 습 니 다.
public class OuterClass$InnerClass {
    public InnerClass(String name,String age){
        this.InnerClass$name = name;
        this.InnerClass$age = age;
    }
    
    
    public void display(){
        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );
    }
}

       따라서 상기 코드 를 보면 내부 유형 은 직접 호출 방법 으로 전달 하 는 매개 변수 가 아니 라 자신의 구조 기 를 이용 하여 들 어 오 는 매개 변 수 를 백업 하 는 것 이다. 자신의 내부 방법 이 실제 적 으로 호출 될 때 자신의 속성 은 외부 방법 으로 전달 하 는 매개 변수 가 아니다.
       여기까지 왜 final 인지 설명 이 안 됐어 요?내부 류 에서 의 속성 과 외부 방법의 매개 변 수 는 겉으로 볼 때 같은 것 이지 만 사실은 그렇지 않다. 그래서 그들 두 가 지 는 임의로 변화 할 수 있다. 즉, 내부 류 에서 내 가 속성 에 대한 변 화 는 외부의 형태 에 영향 을 주지 않 는 다. 그러나 이것 은 프로그래머 의 측면 에서 볼 때 이것 은 불가능 하 다.프로그램의 측면 에서 볼 때 이 두 가 지 는 근본적으로 같은 것 이다. 만약 에 내부 류 가 바 뀌 어야 하 는데 외부 방법의 형 삼 은 바 뀌 지 않 았 다. 이것 은 이해 하기 어렵 고 받 아들 일 수 없 는 것 이기 때문에 매개 변수의 일치 성 을 유지 하기 위해 final 을 사용 하여 형 삼 의 변 하지 않도록 규정 한다.
      간단하게 이해 하면 복사 인용 은 인용 값 이 바 뀌 는 것 을 피하 기 위해 외부 클래스 의 방법 에 의 해 수정 되 는 등 내부 클래스 가 얻 은 값 이 일치 하지 않 기 때문에 final 로 이 인용 을 바 꿀 수 없 게 하 는 것 이다.
      따라서 익명 의 내부 클래스 를 정의 하고 외부 에서 정 의 된 인 자 를 사용 하 기 를 원한 다 면 컴 파일 러 는 이 매개 변 수 를 final 로 참조 하도록 요구 할 것 입 니 다.
       4. 익명 내부 클래스 초기 화
       우 리 는 일반적으로 구조 기 를 이용 하여 특정한 인 스 턴 스 의 초기 화 작업 을 완성 하지만 익명 내부 류 는 구조 기 가 없습니다!그럼 어떻게 익명 내부 클래스 를 초기 화 합 니까?구조 코드 블록 사용!구조 코드 블록 을 이용 하면 익명 내부 클래스 에 구조 기 를 만 드 는 효 과 를 얻 을 수 있 습 니 다.
public class OutClass {
    public InnerClass getInnerClass(final int age,final String name){
        return new InnerClass() {
            int age_ ;
            String name_;
            //            
            {
                if(0 < age && age < 200){
                    age_ = age;
                    name_ = name;
                }
            }
            public String getName() {
                return name_;
            }
            
            public int getAge() {
                return age_;
            }
        };
    }
    
    public static void main(String[] args) {
        OutClass out = new OutClass();
        
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");
        System.out.println(inner_1.getName());
        
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");
        System.out.println(inner_2.getName());
    }
}

기 초 를 공 고 히 하고 기술 을 향상 시 키 며 어려움 을 두려워 하지 않 고 고봉 등반!!!!!!
저작권 성명: 본 고 는 블 로 거들 이 창작 한 글 로 블 로 거들 의 허락 없 이 전재 할 수 없다.

좋은 웹페이지 즐겨찾기