티스토리 뷰

 

그래픽 UI 사용할 때 자주 사용되는 것.

스레드할 때 자주보게 됨.

안드로이드 이벤트 처리

 

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

클래스 속에 포함된 클래스, 인터페이스

 

1.이너클래스

클래스 속에 포함된 클래스.

class A { //아우터 클래스(outer class)
    //멤버 이너클래스
    class B{
        //인스턴스 이너클래스
    }
    static class C {
        //정적 멤버 클래스
    }
    
    void abc(){
        //지역 이너클래스
        class D{
            //지역 클래스
        }
    }
}//class A

(1) 종류

-인스턴스 멤버클래스 : 아우터 클래스가 객체 생성해야만 접근 가능.

-정적 멤버클래스 : 객체 생성하지 않더라도 접근 가능.

-지역 이너클래스 : 메소드 안에 있는 클래스. ex) 안드로이드에서 이벤트(Event) 처리.

(*클래스가 객체가 된다는 것은 메모리가 생긴다. 객체의 방이 생긴다.)

 

(1-1) 인스턴스 멤버 이너클래스

아우터 클래스가 객체 생성해야만 접근 가능. 아우터 클래스의 모든 접근지정자의 멤버에 접근 가능.

아우터 클래스 객체 생성 → 이너클래스 객체 생성

아우터클래스 a = new 아우터클래스();
아우터클래스.이너클래스 b = 아우터클래스객체.new 이너클래스();

_실제 사용 예시)

package aa;
public class A {
	public int a = 3;
	protected int b = 4;
	int c = 5;
	private int d = 6;
    
    void abc() {
		System.out.println("A Class Method");
	}
	
	class B{
		void bcd() {
			System.out.println(a);
			System.out.println(b);
			System.out.println(c);
			System.out.println(d);
            abc();
		}
	}
}

-테스트

package aa;
public class InnerClassTest01 {
	public static void main(String[] args) {
		A a = new A(); //outer class 객체 생성
		A.B b = a.new B();  //인스턴스멤버클래스 생성
		b.bcd();
	}

}

B는 인스턴스 멤버. 반드시 아우터 클래스로 객체가 만들어진 뒤에야 객체 생성 가능. 아우터클래스의 모든 접근지정자에 접근 가능.

3
4
5
6
A Class Method

 

-이너클래스 저장될 때(java_work/bin) $ 사용

아우터클래스 : A.class 이너클래스 : A$B.class

 

-아우터 클래스의 객체를 참조하는 방법

아우터클래스와 이너클래스에 똑같은 변수나 메소드가 있을 때 선택하는 방법. 아우터클래스명.this

package aa;
public class A {
	public int a = 3;
	protected int b = 4;
	int c = 5;
	private int d = 6;
	
	void abc() {
		System.out.println("A Class Method");
	}
	
	class B{
		int a = 10;
		int b = 20;
		
		void abc() {
			System.out.println("Inner B Class Method");
		}
		
		void bcd() {
			System.out.println(this.a); //안쪽 출력
			System.out.println(this.b);  //안쪽 출력
			System.out.println(A.this.a); //아우터 클래스의 a
			System.out.println(A.this.a); //아우터 클래스의 b
			System.out.println(c);
			System.out.println(d);
			abc();
			A.this.abc();  //아우터 클래스의 메소드 abc()
		}
	}
}
package aa;
public class InnerClassTest01 {
	public static void main(String[] args) {
		A a = new A(); //outer class 객체 생성
		A.B b = a.new B();
		b.bcd();  //B의 a, b 사용
	}
}

 

(1-2) 정적 멤버 클래스(static class)

아우터 클래스의 static 멤버만 접근 가능. 아우터 클래스의 객체 생성없이 접근 가능.

?객체 생성없이 접근 가능하다면서 객체는 왜 만들지?

package aa;
public class A {
	public int a = 3;
	protected int b = 4;
	int c = 5;
	private int d = 6;
	
	static int e = 7;
	
	void abc() {
		System.out.println("A Class Method");
	}
	
	static void method2() {
		System.out.println("A Class static Method");
	}
	
	static class C{
		void bcd() {
//			System.out.println(a); //인스턴스 멤버라 객체 생성 후 사용 가능
//			System.out.println(b); //static 클래스에선 static만 사용 가능
			System.out.println(e); //static 멤버라 사용 가능
			System.out.println("static inner class method");
//			abc();  //일반 객체 메소드라 오류
			method2();
		}
	}
}

-메인 함수에서 객체 생성하고 접근하는 방법

package aa;
public class InnerClassTest01 {

	public static void main(String[] args) {
		A a = new A(); //outer class 객체 생성
		A.B b = a.new B();
		b.bcd();  //B의 a, b 사용
		
		//static 멤버 객체 생성? 접근법
		A.C c = new A.C();//아우터클래스의 객체 생성없이 바로 접근하고 바로 객체 생성.
		c.bcd();
	}
}

원래는 outer class의 객체를 생성하고 접근해야 하는데 static이라 바로 접근 가능.

10
20
3
3
5
6
Inner B Class Method
A Class Method
7
static inner class method
A Class static Method

 

(1-3) 지역 이너클래스

ex) 안드로이드에서 이벤트(Event) 처리. 메인 액티비티 안에 이벤트. 그 이벤트 안에 클래스가 들어감.

메소드 안에 있는 클래스. 메소드 내부에서만 유효(메소드 지역변수는 final만 사용)

class A {
	int a = 3; //필드
    
	void abc(){
		int b = 5;  //지역변수
                    //자동으로 final 추가. 값 변경 불가능
    
   		class B {  //메소드 내부 클래스 - 지역 클래스
			void bcd(){
				System.out.println(a);  // 필드 접근 가능
				System.out.println(b);  // 지역 변수 접근 가능
				a = 7;  // 필드 변수 변경 가능
				b = 9;  // 지역 변수 변경 불가능
			}
		}
		B bb = new B(); //인스턴스 멤버 클래스 - 객체 생성
		bb.bcd();  //접근 가능    
	}//method abc   
}

-아우터 클래스의 필드는 모두 접근 가능. 필드값 변경 가능. 지역변수 변경 불가능.

-메소드 안의 지역변수 : final만 사용 가능(상수화된 것). (*Java는 자동적으로 추가해주지만 안드로이든 안 해줌)

-메소드 안의 클래스지만 메소드와는 분리된 것이라고 간주.

 

_예제)

package aa;
public class A {
	public int a = 3;
	protected int b = 4;
	int c = 5;
	private int d = 6;
	
	static int e = 7;
	
	void abc() { //3. 메소드 안에 클래스
		int f = 30;
		System.out.println("A Class Method");
		
		class D{
			void cde() {
				System.out.println("D class cde Method");
				System.out.println(a); //접근 가능
				System.out.println(b); //접근 가능
				System.out.println(c); //접근 가능
				System.out.println(d); //접근 가능
				System.out.println(e); //접근 가능
				System.out.println(f); //접근 가능
			}
		}
		D dd = new D(); //객체 생성
		dd.cde(); //호출
	}//void abc
}
package aa;
public class InnerClassTest01 {
	public static void main(String[] args) {
		A a = new A(); //outer class 객체 생성
		A.B b = a.new B();
		b.bcd();  //B의 a, b 사용
		System.out.println("-------------------");
		//static 멤버 객체 생성? 접근법
		A.C c = new A.C();//아우터클래스의 객체 생성없이 바로 접근하고 바로 객체 생성.
		c.bcd();
		
		//3.
		System.out.println("-------------------");
		a.abc();
		
	}
}

 

-생성클래스명

지역 이너클래스 클래스명. 이름 중복되는 경우를 고려해서 번호가 매겨짐.

_예시

package bb;
public class A {  //A.class
	void abc() {
		class B{}  //A$1B.class
		class C{}  //A$2C.class
	}
	void bcd() {
		class C{}  //A$2C.class
		class D{}  //A$1D.class
	}
}

 

 

(2) 익명이너클래스

익명(이름을 알 수 없음) + 인스턴스 이너클래스

한번에 객체를 2개 이상 생성 불가능.

package aa;
interface C{
	public abstract void dcd(); //public abstract 생략해도 붙어있는 걸로 간주
}//인터페이스형 변수(?)

public class A1 {
	C b = new B(); //인터페이스형 변수 C로 생성한 객체
	void abc() {
		b.dcd();
	}
	
	class B implements C{//interface C의 추상메소드 구현해줘야 함.

		@Override
		public void dcd() {
		System.out.println("익명클래스 사용");			
		}	
	}
}
package aa;

public class A2 {
	C b = new C() {//인터페이스 객체 못 만듦. → 추상메소드 구현하면 됨(?)
		@Override
		public void dcd() {
			System.out.println("Anonymous");
		}
	};
	void abc() {
		b.dcd();
	}
}

-메인 함수에서 객체 생성 및 출력

package aa;

public class AnonymousTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		A1 a1 = new A1();
		a1.abc();
		
		//익명2
		A2 a2 = new A2();
		a2.abc();
	}

}

 

익명이너클래스. 인터페이스 C안에 있는 것만 부를 수 있음.

_관련 예시)

package aa;

interface C{
	public abstract void dcd(); //public abstract 생략해도 붙어있는 걸로 간주
}//인터페이스형 변수(?)

public class A1 {
	B b = new B(); //인터페이스형 변수 C로 생성한 객체
	void abc() {
		b.dcd();
		b.kkk();
		
	}
	
	class B implements C{//interface C의 추상메소드 구현해줘야 함.

		@Override
		public void dcd() {  //메소드 오버라이딩
		System.out.println("익명클래스 사용");			
		}
		
		//메소드 추가해도 괜찮음.
		public void kkk() {
			System.out.println("method kkk");
		}
	}
}
package aa;

public class A2 {
	C b = new C() {//인터페이스 객체 못 만듦. → 추상메소드 구현하면 됨(?)
		//인터페이스 이름으로 만든 것. 구현한 것.
		//interface C에만 있는 것을 (외부에서 부를 수 있음). 추가한 것은 내부에서만 사용 가능.
		//클래스 이름 없으므로 밖에서 못 부름.
		//인터페이스 오버라이딩 목적으로만 사용.
		
		@Override
		public void dcd() {
			System.out.println("Anonymous");
			//메소드 kkk를 부르고 싶다면
			kkk();
		}
		public void kkk() {
			System.out.println("method kkk");  //추가한 것은 외부에서 못 부름.
		}
	}; //추상메소드 구현했으므로 세미콜론(;) 붙여줌
	void abc() {
		b.dcd();
	}
}
package aa;

public class AnonymousTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		A1 a1 = new A1();
		a1.abc();
		
		A1.B b = a1.new B();
		b.kkk();
		b.dcd();
		
		//익명2
		A2 a2 = new A2();
		a2.abc();
	}

}

 

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

(1번으로 하는 게 정석(?) 근데 실제로는 4번을 많이 보게 될 것)

_type1

package cc;
interface A{
	void abc();
}

class B implements A{
	@Override
	public void abc() {
		System.out.println("추상메소드 abc()");
	}	
}
public class C { //구현하고 사용
	void cde(A a) {
		a.abc();
	}
}
package cc;
public class Ctest {
	public static void main(String[] args) {
		// 1
		C c1 = new C();
		A a1 = new B();
		c1.cde(a1);
		
		// 2
		C c2 = new C();
		c2.cde(new B());
		
		//3		
		C c3 = new C();
		A a = new A() {//추상메소드 구현
			@Override
			public void abc() {
				System.out.println("익명으로 메소드 구현");
			}
		};
		c3.cde(a1);
		
		//4 - 안드로이드에서 자주볼 것.
		C c4 = new C();
		c4.cde(new A() { //cde 메소드 안에서 객체 생성해 매개변수. 그걸 cde에 전달.
			@Override
			public void abc() {
				System.out.println("익명 참조변수 없이 사용");
			}	
		});
	}
}

 


2. 이너인터페이스

클래스 내부의 인터페이스. 이너인터페이스는 정적(static)이너인터페이스만 가능 (static 생략시 자동 추가)

UI의 이벤트 처리에 가장 많이 사용(클릭, 터치) - 안드로이드에서 자주 사용

 

(1) 객체 생성 및 사용

_예시)

package dd;

public class A {
	public void abc() {
		System.out.println("A class abc method");
	}
	
	static interface B{ //inner interface B
		void bcd(); //abstract method
	}
}
class C implements A.B{ //A의 객체를 만들지 않더라도 바로 접근할 수 있음.

	@Override
	public void bcd() {
		System.out.println("method bcd");
	}
}
package dd;

public class InnerinterfaceTest {

	public static void main(String[] args) {
		C c = new C();
		c.bcd();
		
		A.B c2 = new C();
		c2.bcd();
		
		//익명으로
		A.B c3 = new A.B() {

			@Override
			public void bcd() {
				System.out.println("익명으로 구현한 A.B인터페이스의 bcd 메소드");
			}
		};
		c3.bcd();
	}
}

 

_대표적 예시) API(CH13 P21)

안드로이드에서 자주 볼 수 있는 것.

package button;

class Button { //interface OnClickListener가 없을 때 오류 뜨던데...생기니까 사라짐 
	OnClickListener ocl;
	void setOnClickListener(OnClickListener ocl) {
		this.ocl = ocl;
	}
	
	interface OnClickListener{  //static 생략?
		public abstract void onClick();
	}
	void click() {
		ocl.onClick();
	}
}
package button;

public class ButtonTest {

	public static void main(String[] args) {
		Button button1 = new Button();
		button1.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick() {
				System.out.println("개발자1. 음악재생");
			}
		});
		button1.click();
		
		Button button2 = new Button();
		button2.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick() {
				System.out.println("개발자2. Naver");
			}
		});
		button2.click();
	}

}

'수업 > └Java' 카테고리의 다른 글

[CH12]Thread  (0) 2022.02.07
[실습문제6_1]Person, Customer, Test  (0) 2022.02.04
[CH09]추상 클래스(abstract class)와 인터페이스(interface)  (0) 2022.02.03
[Ch08]자바 제어자 : final  (0) 2022.02.02
[00]Wrapper class  (0) 2022.02.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함