이너클래스와 이너 인터페이스

jaegeunsong97·2023년 1월 14일
0
post-thumbnail

2023_1_14_TIL

인스턴스 멤버 이너 클래스

  • 객체 내부에 멤버 형태로 존재
  • outer class의 모든 접근 지정자 멤버에 접근 가능
  • 순서 -> 아우터 클래스 -> 이너 클래스
  • 이너 클래스는 독립적 사용 불가능
  • 인스턴스 이너 클래스 객체 생성
    • 아우터 클래스 객체 생성 -> 이너 클래스 객체 생성
    • 아우터 클래스 객체를 참조하기 위해서(반드시 참조해서 생성해야 함)
    • 이너 클래스 객체의 자료형 A.B 임 (B 아님)
class A {
    public int a = 3;
    protected int b = 4;
    int c = 5;
    private int d = 6;
    void abc() {
        System.out.println("A 클래스 메소드 abc()");
    }
    class B {
        void bcd() {
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
            System.out.println(d);
            abc();
        }
    }
}
public class CreateObjectAndAccessMember {
    public static void main(String[] args) {
        A a = new A();
        A.B b = a.new B();
        b.bcd();
    }
}
  • 아우터 클래스의 객체 참조
    • 아우터클래스.this.아우터클래스멤버 -> 여기서 this는 아우터 클래스를 의미
    • 반면에 this.~~ -> 이너클래스쪽 참조 this임
class A {
    int a = 3;
    int b = 4;
    void abc() {
        System.out.println("A 클래스 메소드");
    }
    class B {
        int a = 3;
        int b = 4;
        void abc() {
            System.out.println("B 클래스 메소드");
        }
        void bcd() {
            System.out.println(a);
            System.out.println(b);
            abc();
            System.out.println(A.this.a);// 요 부분
            System.out.println(A.this.b);// 요 부분
            A.this.abc();
        }
    }
}
public class UseMembersOfOuterClass {
    public static void main(String[] args) {
        A a = new A();
        A.B b = a.new B();
        b.bcd();
    }
}

정적 멤버 이너 클래스

  • 아우터 클래스의 객체 생성 없이 객체 생성 가능 -> 아우터 클래스 중 정적 멤버만 사용가능
  • 정적 클래스 객체 생성하기
class A {
    int a = 3;
    static int b = 4;
    void method1() {
        System.out.println("instance method");
    }
    static void method2() {
        System.out.println("static method");
    }
    static class B {
        void bcd() {
            System.out.println(b);
            method2();
        }
    }
}
public class CreateObjectAndAccessMember {
    public static void main(String[] args) {
        A.B b = new A.B();
    }
}

지역 이너 클래스

  • 메서드 안에서 정의됨
  • 메서드가 호출될 때만 메모리에 로딩
  • 형태 -> 아우터클래스& + 숫자 + 지역ㅇ너클래스.class -> 숫자있는 이유는 메소드가 여러개 있으면 구분 할려고 ㅇㅇ
  • 지역 이너 클래스 객체 생성
    • 아우터클래스 멤버 접근 지정자와 상관없이 사용 가능
    • 자신이 정의된 메소드 내의 지역변수도 클래스 내부에서 사용 가능
      • 해당 지역변수는 final로 선언되어야 함(약속)
    • 해당 메소드 안에서만 객체 생성이 가능 -> 일반 클래스의 객체 생성과 동일
class A {
    int a = 3;
    void abc() {
        final int b = 5;
        class B {
            void bcd() {
                System.out.println(a);
                System.out.println(b);
                a = 5;
            }
        }
        B bb = new B();// 요 부분입니다요~~
        bb.bcd();
    }
}
public class AccessMemberAndLocalVariable {
    public static void main(String[] args) {
        A a = new A();
        a.abc();
    }
}

익명 이너 클래스의 정의와 특징

  • 위치에 따라 분류하는 익명 이너 클래스
    • 인스턴스 익명 이너 클래스 -> 클래스의 중괄호 바로 아래에 사용
    • 지역 익명 이너 클래스 -> 메서드 내부에서 사용
  • 인터페이스를 상속한 이너 클래스를 생성해 인터페이스 객체 생성
class A {
    C c = new B();
    void abc() {
        c.bcd();
    }
    class B implements C {// 여어기
        public void bcd() {
            System.out.println("인스턴스 이너 클래스");
        }
    }
}
interface C {
    public abstract void bcd();
}
public class AnonymousClass_1 {
    public static void main(String[] args) {
        A a = new A();
        a.abc();
    }
}
  • 익명 이너 클래스를 활용해 인터페이스 객체 생성
    • 익명 이너 클래스 사용시 -> 항상 부모 타입으로만 선언
    • 오버라이딩 메소드 내부에서 호출 가능 -> 작성 내용 많다? -> 메소드 분리 후 작성
class A {
    C c = new C() {// 여어기
        public void abc() {
            System.out.println("익명 이너 클래스");
        }
    };
    void bcd() {
        c.abc();
    }
}
interface C {
    public abstract void abc();
}
public class AnonymousClass_2 {
    public static void main(String[] args) {
        A a = new A();
        a.bcd();
    }
}

익명 이너 클래스를 활용한 인터페이스 타입의 입력 매개 변수 전달

  • 인터페이스 객채를 생성하고, 메소드의 입력 매개변수로 전달하는 방법 4가지
    • B() 생성자를 이용해, 객체 A 타입의 참조변수에 저장 -> 매개변수로 넘기기
    • 귀찮게 객체의 참좃값만을 전달할 목적? -> 입력매개변수 위치에 new키워드로 객체 생성 -> 객체의 참좃값 메소드로 전달
    • 익명 이너 클래스를 사용해서 객체 생성 -> 객체 참조하는 변수를 입력매개변수로 전달
    • 메소드 입력매개변수자리에 곧바로 익명 이너클래스 객체 생성 후 전달
      • 이벤트 처리에 많이 사용됨
  • 클래스 정의 및 참조 변수명을 사용/미사용했을 때 입력매개변수 객체 전달
interface A {
    public abstract void abc();
}
class B implements A {
    public void abc() {
        System.out.println("입렵매개변수 전달");
    }
}
class C {
    void cde(A a) {
        a.abc();
    }
}
public class AnonymousClass_3 {
    public static void main(String[] args) {
        C c = new C();
   		// 방법 1 클래스명 O 참조 변수 O
        A a = new B();
        a.abc();
		// 방법 2 클래스명 O 참조 변수 X
        c.cde(new B());
    }
}
  • 클래스 미정의 및 참조 변수명을 사용/미사용했을 때 입력개매변수 전달
interface A {
    public abstract void abc();
}
class C {
    void cde(A a) {
        a.abc();
    }
}
public class AnonymousClass_4 {
    public static void main(String[] args) {
        C c = new C();
		// 방법 3 클래스명 X + 참조 변수명 O
        A a = new A() {
          public void abc() {
              System.out.println("입력매개변수 전달");
          }
        };
        c.cde(a);
		// 방법 4 클래스명 X 참조 변수명 X
        c.cde(new A() {
           public void abc() {
               System.out.println("입렵매개변수 전달");
           }
        });
    }
}
  • 익명 이너 클래스 사용하면 직접 클래스 생성 X -> 하지만 여러 객체 생성? -> 직접 클래스 잡자

이너 인터페이스의 정의와 특징

  • 이벤트 처리에 많이 사용
  • 정적 이너 인터페이스만 존재
  • 아우터클래스명$이너인터페이스명.class 형태
  • 일반적인 인터페이스 생성 방식과 같음
    • 차이점 -> 클래스 내부에 인터페이스 존재 -> 클래스명.인터페이스명(객체 타입)
class A {
    static interface B {// static 자동임 ㅇㅇ
        public abstract void bcd();
    }
}
class C implements A.B {// <---
    public void bcd() {
        System.out.println("이너 인터페이스 구현 클래스 생성");
    }
}
public class CreateObjectOnInnerInterface {
    public static void main(String[] args) {
        A.B ab = new C();
        C c = new C();

        c.bcd();

        A.B b = new A.B() {// 요부분 <---
            public void bcd() {
                System.out.println("익명 이너 클래스로 객체 생성");
            }
        };
        b.bcd();
    }
}

이벤트 처리기능 작성

class Button {
    OnClickListener ocl;
    void setOnClickListener(OnClickListener ocl) {
        this.ocl = ocl;
    }
    interface OnClickListener {
        public abstract void onClick();
    }
    void onClick() {
        ocl.onClick();
    }
}
public class ButtonAPIExample {
    public static void main(String[] args) {
        Button btn1 = new Button();
        btn1.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick() {
                System.out.println("개발자 1: 음악 재생");
            }
        });
        btn1.onClick();

        Button btn2 = new Button();
        btn2.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick() {
                System.out.println("개발자 2: 네이버 접속");
            }
        });
    }
}
profile
현재 블로그 : https://jasonsong97.tistory.com/

0개의 댓글