익명 구현 객체(무명 클래스) anonymous class  => 인터페이스로 구현

    -명시적으로 구현클래스를 작성하지 않고, 바로 구현 객체를 얻는 방법이다.

    이름이 없는 클래스라서 익명이라고 한다.

    -인터페이스의 추상 메서드를 익명구현객체라고 해도 다시 재정의를 하여야 한다.

    -추가적으로, 필드와 메서들를 선언 가능하나 익명 구현객체 안에서만 사용 가능하다.

    -외부에서 접근 불가

    -인터페이스 참조변수로 접근 역시 불가능하다.,(원래 타입이 없다. 객체생성 불가)

    package kr.co.kihd.anonymous;
    
    //인터페이스에 추상메서드가 1개만 오로지 존재하면 함수적 인터페이스.(람다식)
    public interface Soundable {
    	public void sound();
    	
    }
    
    package kr.co.kihd.anonymous;
    
    public class SoundTest {
    
    	public static void main(String[] args) {
    		//익명구현객체(이름 없음) -- UI이벤트 처리나 (스레드 객체) 간편하게 생성시 사용.
    								   //잠깐 사용할 목적				
    		Soundable soundable = new Soundable() { // (원래)타입이 인터페이스 
    			
    			//내부적으로 클래스이니까 멤버들을 선언가능
    			//하지만, 외부에서 접근 불가
    			
    			int a = 10;
    			
    			public void method() {
    				System.out.println("익명구현객체 메서드");
    			}
    			
    			@Override
    			public void sound() {
    				String str = "냄비";
    				System.out.println("첫번째 익명구현객체: " + str);
    				System.out.println(str + "에 물을 담습니다.");
    				System.out.println(str + "에 숟가락으로 탕탕소리를 냅니다.");
    			
    				this.method();
    				System.out.println(this.a);
    			}
    			
    		};
    		
    		Soundable soundable1 = new Soundable() { // (원래)타입이 인터페이스 
    			
    			//내부적으로 클래스이니까 멤버들을 선언가능
    			//하지만, 외부에서 접근 불가
    			
    			int a = 20;
    			
    			public void method() {
    				System.out.println("밥그릇 익명구현객체 메서드");
    			}
    			
    			@Override
    			public void sound() {
    				String str = "밥그릇";
    				System.out.println("두번째 익명구현객체: " + str);
    				System.out.println(str + "에 물을 담습니다.");
    				System.out.println(str + "에 숟가락으로 탕탕소리를 냅니다.");
    			
    				this.method();
    				System.out.println(this.a);
    			}
    			
    		};
    		
    		
    		soundable.sound();
    		soundable1.sound();
    
    	}
    
    }
    

     

    익명 자손 객체(무형 클래스) => 클래스로 구현

    명시적으로 자손클래스를 작성하지 않고, 바로 자손 객체를 얻는 방법이다.

    -이름이 없는 클래스라서 익명이라고 한다.

    -원 타입이 조상클래스 타입이라서, 통상 익명 자손 객체는 조상의 메서드를 오버라이딩하여 잠시 사용할 용도로 사용한다.

    (UI이벤트 처리나 쓰레드 객체를 간편히 생성)

    -추가적으로, 필드와 메서드를 선언가능하나 익명 자손 객체 안에서만 사용 가능하다.

    외부에서 접근 불가

    -조상타입 참조변수로 접근 역시 불가능하다.(원래타입이 없다.)

     

    package kr.co.kihd.anonymous;
    
    public class Parent {
    
    	public Parent(){
    		System.out.println("조상 생성자");
    	}
    	
    	public void method() {
    		System.out.println("Parent 메서드");
    	}
    	
    }
    
    package kr.co.kihd.anonymous;
    
    public class ChildTest {
    
    	public static void main(String[] args) {
    		//익명자손객체(이름없음) -- UI이벤트 처리나 스레드 객체 간편하게 생성시 사용.
    		Parent parent = new Parent() {			//원래타입이 클래스임.
    			
    			int b = 10;
    			
    			public void method1(){
    				System.out.println("익명자손객체 메서드");
    			}
    			
    			@Override
    			public void method() {
    				int a = 10;
    				System.out.println("a : " + a);
    				System.out.println(this.b);
    				this.method1();
    			}
    		};
    
    		parent.method();
    //		parent.b;			부모타입 멤버가 아님
    //		parent.method1();	부모타입 멤버가 아님
    							
    	}
    
    }
    

     


    중첩(내부) 클래스 - inner(nested) class

    중첩 클래스의 개념

    -클래스 안에 멤버로써 선언되어진 클래스를 칭한다.

    -해당 클래스 내에서만 사용되어질 클래스를 중첩클래스로 선언한다.,(외부에서 사용 안함)

    -GUI애플리케이션(AWT, SWING, 안드로이드 프로그램)의 이벤트 처리에서 주로 사용된다. 

    또한 웹애플리케이션에서 많이 사용된다.

     

    중첩클래스의 장점

    -중첩클래스에서 외부클래스의 멤버에 쉽게 접근이 가능하다.

    -코드의 복잡성을 줄일 수 있다.(캡슐화)

     

    중첩클래스의 종류와 특징

    중첩 클래스의 종류는 변수의 선언위치에 따른 종류와 동일하다

    유효범위 및 성질도 변수와 유사하다.

    중첩클래스의 바이트 코드 파일

    A $ B .class 외부클래스 $ 멤버클래스,

    A $1 B .class 외부클래스 $1 로컬클래스.

    (멤버클래스와 로컬 클래스는 순번으로 구분을 짓는다)


    인스턴스 멤버클래스

    외부 클래스가 생성되어야, 내부 클래스를 사용할 수가 있다.

    *** static은 인스턴스 생성 없이도 접근이 가능해야 하므로, 인스터스 멤버클래스에는

    멤버변수나 메서드로 선언이 불가함에 주목하자,

     

    언제 인스턴스가 생성될지는 아무도 모른다. 아여, 인스턴스 멤버 클래스에는 

    static멤버가 올 수가 없다. 

     

    항상 A의 인스턴스가 생성 되어야함.

    A.B b = a. new B()

     

    정적 멤버 클래스

    외부 클래스 A가 생성되지 않아도 접근가능하다.

    ***인스턴스 멤버변수는 new생성자를 통해 인스턴스가 만들어져야만 접근가능하다.

     

    static 키워드로 선언된 클래스, 모든 종류의 필드. 메서드 선언가능

     

    로컬 클래스 - 메서드 내 작성 후 사용

    기능적인 것들을 먼저 정의 -> 객체생성 

    Thread클래스의 run 메서드 사용

    지역클래스는 메서드 내에서 선언과 사용

     

    package kr.or.kihd.nested;
    
    public class NestedTest {
    	
    	//인스턴스 멤버 클레스
    	class A {
    		int iv = 100;
    //		static int cv = 200; //static 멤버 변수는 사용불가.
    		
    		public A() {
    			System.out.println("A생성자 호출");
    		}
    		
    		public void method() {
    			System.out.println("A클레스의 method()호출");
    		}
    		
    //		public static void method2() { 
    //			
    //		}
    	
    	}
    	
    	//정적 멤버 클레스
    	static class B {
    		int iv = 100;
    		static int cv = 500; // NestedTest.B.cv 형태로 접근하면 된다.
    		
    		public B() {
    			System.out.println("B 생성자 호출");
    		}
    		
    		public void method1() {//인스턴스 메서드
    			System.out.println("B클레스의 method1()호출");
    		}
    		
    		static void method2() {//정적 메서드
    			System.out.println("B클레스의 method1()호출2");
    		}
    		
    	}
    	
    	public void method1() {
    		//로컬클레스 : 메서드내에 선언과 사용(잠깐 사용할 용도) 이벤트처리 스레드 처리
    		class C {
    			int iv = 200;
    //			static cv = 700;   //static 멤버 선언 불가
    			public C() {
    				System.out.println("로컬클레스C 생성자 호출");
    			}
    			public void Imethod() {
    				System.out.println("로컬클레스C 메서드 호출");
    			}
    		}
    		//로컬클래스는 해당 메서드 내에서만 사용이 가능하다는 것에 주목하자. 
    		C c = new C();
    		System.out.println(c.iv);
    		c.Imethod();
    	}
    	
    	
    	public static void main(String[] args) {
    		NestedTest nestedTest = new NestedTest();
    		//인스턴스 멤버 클레스는 외부클레스의 인스턴스가 반드시 있어야 생성가능함.
    		NestedTest.A a = nestedTest.new A();
    		System.out.println(a.iv);
    		a.method();
    		System.out.println("-------------------------------");
    		
    		//정적 클레스 접근 : 외부클레스의 객체생성없이 인스턴스가 없이도 접근 가능함.
    		System.out.println(NestedTest.B.cv);
    		NestedTest.B.method2();
    		System.out.println("-------------------------------");
    		
    		//로컬 클래스가 포함된 메서드 호출
    		nestedTest.method1(); 
    		System.out.println("-------------------------------");
    		
    		
    	}
    
    }
    

    인스턴스 클레스 , 정적 멤버 클래스 예제

    package kr.or.kihd.nested;
    
    public class A {
    	
    	public A() {
    		System.out.println("-----------------------------------------");
    		System.out.println("외부클래스 A의 생성자 호출");
    		
    		B b = new B(); //인스턴스 멤버클레스는 외부클레스 A의 멤버라서 객체생성 가능
    		System.out.println(b.a);
    		b.method1();
    		
    		C c = new C();
    		System.out.println(c.a);
    		System.out.println(C.c);
    		c.method1();
    		c.method2();
    		
    	}
    	
    	//인스턴스 멤버클레스 B
    	class B {
    		int a = 10;
    //		static int cv = 20;  //클레스가 언제생성될지 몰라서 
    		public B() {
    			System.out.println("중첩클레스 B의 생성자 호출");
    		}
    		public void method1() {
    			System.out.println("B클레스 멤버메서드 호출");			
    		}
    //		static void method2() {
    //			
    //		}
    	}
    	
    	//정적 멤버 클래스 C
    	static class C{
    		int a = 10;
    		static int c = 20; 
    		public C() {
    			System.out.println("정적멤버클레스 C의 생성자 호출");
    		}
    		public void method1() {
    			System.out.println("정적멤버클레스 C의 method1() 호출");			
    		}
    		static public void method2() { //정적메서드 
    			System.out.println("정적멤버클레스 C의 정적메서드 method2() 호출");			
    		}
    			
    	}
    	
    }
    
    package kr.or.kihd.nested;
    
    
    public class ATest {
    
    	public static void main(String[] args) {
    		A a = new A();
    		//인스턴스 클레스인 B는 반드시 외부 클레스 A의 인스턴스가 있어야
    		//생성이 가능하다.
    		A.B b = a.new B();
    		b.method1();
    		System.out.println("-----------------------------------------");
    		
    		System.out.println(A.C.c);
    		A.C.method2();
    		//정적 멤버 클래스인 C는 외부클레스 A의 인스턴스가 있던 없던 
    		//상관없이 접근 가능하다.
    		A.C c = new A.C();
    		System.out.println(c.a);
    		c.method1();
    		System.out.println("------------------------------------------");
    		
    		
    	}
    
    }
    

    중첩클래스 접근제한 예제

     

    결론 : 중첩클래스에서의 인스턴스 필드나 메서드는 언제든지 생성가능하지만,
    정적필드나 정적메서드는 정적클래스에서만 가능하다.

    package kr.or.kihd.nested2;
    
    public class Aaccess {
    	
    	//인스턴스 멤버클래스
    	class B {
    		public B() {
    			System.out.println("인스턴스 멤버 클래스B 생성자");
    		}
    	}
    	
    	//정적 멤버클래스
    	static class C {
    		public C() {
    			System.out.println("정적멤버클래스C 생성자");
    		}
    		
    	}
    	
    	//인스턴스 멤버(필드)
    	B b = new B();
    	C c = new C();
    	
    	//인스턴스 멤버 메서드
    	//method1()을 사용할때 쯤은, 이미 외부클래스 Aaccess의 
    	//인스턴스가 만들어진 상태일것이다.
    	public void method1() {
    		System.out.println("method()");
    		//지역변수
    		B b = new B();
    		C c = new C();
    	}
    	
    	//정적 멤버 
    //	static B b1 = new B(); //(X) B클래스는 인스턴스 멤버 클래스이기 떄문에,
    						   //static이 붙으면 안됨.
    	static C c1 = new C(); 
    	Aaccess.B c2 = new B(); 
    //	static Aaccess.B c3 = new B(); //(X) B클래스는 인스턴스 멤버 클래스이기 떄문에,
    								   //static이 붙으면 안됨.
    	//static은 static만 접근이 가능하다.
    	public static void method2() {
    		System.out.println("method2");
    //		B b = new B(); //(X) B클래스는 인스턴스 멤버 클래스이기 떄문에,
    		   			   //static이 붙으면 안됨.   
    		C c = new C(); //정적메서드 이기떄문에 정적 로컬 변수로 선언을 해도 무방함.
    	}
    	//결론 : 중첩클래스에서의 인스턴스 필드나 메서드는 언제든지 생성가능하지만,
    	//정적필드나 정적메서드는 정적클래스에서만 가능하다.
    }
    
    package kr.or.kihd.nested2;
    
    public class ATest {
    
    	public static void main(String[] args) {
    		
    		Aaccess a = new Aaccess();
    		Aaccess.B b = a.new B();
    		a.method1();
    
    	}
    
    }
    

    중첩클래스의 맴버들에게 접근 예제

    package kr.or.kihd.inneroutter;
    
    public class Outside {
    	
    	//필드선언
    	String str = "Outside-field";
    	
    	//멤버메서드
    	public void method() {
    		System.out.println("Outside-method() 호출");
    	}
    	
    	class Inner {
    		//필드선언
    		String str = "Inner-field";
    		//멤버메서드
    		public void method() {
    			System.out.println("Inner-method() 호출");
    		}
    		//멤버 메서드
    		public void showInfo() {
    			//여기에서 이this는 Inner클래스의 this이다
    			System.out.println(this.str);
    			this.method();
    			//외부클래스의 접근하는 방법
    			//외부클래스명.this.외부클래스멤버이름
    			System.out.println(Outside.this.str);
    			Outside.this.method();
    		}
    	}
    	
    	public void show() {
    		System.out.println("--------------------------------");
    		//외부클래스 영역에서의 this는 당연히 Outside클래스를 말한다.
    		System.out.println(this.str);
    		this.method();
    		
    		//외부클래스에서 내부클래스로 접근을 할려면 보이지 않는다.
    		//인스턴스를 하나 생성해서 중첩클래스의 맴버들에게 접근하면 된다.
    		Inner inner = new Inner();
    		inner.showInfo();
    	}
    	
    }
    
    
    package kr.or.kihd.inneroutter;
    
    public class OutsideTest {
    	
    	public static void main(String[] args) {
    		Outside outside = new Outside();
    		Outside.Inner inner = outside.new Inner();
    		inner.showInfo();
    		
    		outside.show();
    	}
    	
    }
    

     

    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기
    loading