static inner class vs non static inner class

2022. 12. 10. 17:22카테고리 없음

내부클래스 

- 클래스 안의 클래스 

 

class A{// 일반 클래스 2개


}
class B{

}

장점:

- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.(객체 생성 없이도 A의 멤버 접근 가능)

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

class A{//외부 클래스
	class B{//내부 클래스
	
    }

}

 

package main1100;

class AAA{//AAA는 BBB의 외부 클래스 
	int i = 100;

	
	class BBB{//BBB는 AAA의 내부 클래스
		void method() {
			
			  AAA a = new AAA(); System.out.println(a.i);
		
			System.out.println(i);//객체 생성없이 외부 클래스의 멤버 접근 가능
			
		}
		
		
	}
	
	
}

/*
 * class CCC{ BBB b = new BBB(); //사용하지 못한다. }
 */


public class InnerTest {
	public static void main(String[] args) {
		//BBB b= new BBB (); 이너 클래스로 들어가서 이런식으로 접근 못함
		//b.method();
		
	}
	

}

 BBB클래스는 이제 AAA 클래스의 멤버처럼 다뤄지게 되어있다 외부에서 사용시에는 AAA클래스를 객체생성한 이후에 사용할수있다,  그렇기에 불필요요한 노출 없이 캡슐화 되어 AA클래스 내부에서 사용하기 편리하다.

 

 

내부 클래스의 종류와 특징

- 내부 클래스의 종류와 유효범위(scope)는 변수와 동일 

class Outer{
	class InstanceInner{}     //iv(인스턴스 클래스)
    static class StaticInner{} //cv( 스태틱 클래스)
    
    void myMethod(){
    	class LocalInner{}// lv( 지역 클래스)
    }
}

클래스 안에 상태 (변수 ) 종류: iv ,cv,lv 와 특징이 같다.

 

인스턴스 클래스 : 외부 클래스의 멤버 변수 선언 위치에 선언하며, 외부 클래스의 인스턴스멤버 처럼 다루어진다, 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용 될 목적으로 선언된다.

스태틱 클래스: 외부 클래스의 멤버 변수 선언 위치에 선언하며, 외부 클래스의 static 멤버 처럼 다루어진다, 주로 외부 클래스의 static멤버 특히 static 메소드에서 사용될 목적으로 선언된다.

지역클래스: 외부 클래스의 메서드나 초기화 블럭 안에 선언하며,선언된 영역 내부에서만 사용 될 수 있다.

익명클래스: 클래스의 선언과 객체의 생성을 동시에 하여 이름없는 클래스( 일회용)

 

 

내부 클래스의 제어자 와 접근성

- 내부 클래스의 제어자는 변수에 사용가능한 제어자와 동일

class Outer{// class에 접근제어자는 디폴트, public 밖에 안된다.
	private class InstanceInner{}// 내부클래스는 다 가능하다.
    protected static class StaticInner{}
    
    void myMethod(){
    	class LocalInner{}
 
  }

}
package main1100;

public class Ex7_12 {
	class InstanceInner{//인스턴스 내부 클래스
		int iv = 100; 
		//static int cv =100;//에러 ! static변수를 선언 할 수 없다.
		final static int CONST =100;//final static은 상수이므로 허용 
		
		
		
	}
    //static 내부 클래스 
	static class StaticInner{ 
		int iv = 200;
		static int cv = 200 ;//static클래스만 static멤버를 정의 할 수 있다.
	}
    
    //지역 내부 클래스 
	void myMethod() {
		class LocalInner{
			int iv =300;
			//static int cv = 300;//에러 ! static변수를 선언 할 수 없다.
			final static int CONST =300;//final static 은 상수이므로 허용
			
			
		}
		int i = LocalInner.CONST;//ok 메소드 내에서 만 가능
	}
	
	public static void main(String[] arg) {
		
		System.out.println(InstanceInner.CONST);
		System.out.println(StaticInner.cv);
		//System.out.println(LocalInner.CONST);//에러 , 지역 내부 클래스는 메소드 내에서만
	}
}

static 내부 클래스 : static이라는 것이 객체 생성 없이  사용  가능해야 한다. 일반 클래스가 

staic을 가지게 되면   모순이 발생하게 된다, 인스턴스 멤버니까 객체를 생성해서 쓸수 있는데 , 그냥 쓸수 있다.

 

인스턴스 멤버가 static 멤버를 사용할 수있지만 cv가 iv를 사용 할수 없다.

static 내부 클래스에서는 외부 클래스의 인스턴스 멤버에 접근 할 수 없다.

 

그러나 상수 같은 경우는  static 멤버를 가질수 있다. 보통 상수의 경우에 final static을 많이 붙힌다.

지역내부 클래스는  상수를 메소드 내에서만 사용 가능하다.

 

 

package main1100;

public class Outer {
	private int outerIv =0;
	private static int outerCv =0;

	class InstanceInner{
		int iiv = outerIv;// 외부 클래스의 private 멤버도 접근가능하다. 
		int iiv2 = outerCv;
		
	}
	
	static class StaticInner{
		static int scv = outerCv;
		
		
	}
	
	//메소드 지역변수 
	void myMethod() {
		int Iv =0; //값이 바뀌지 않는 변수는 상수로 간주
		final int Lv =0;//JDK1.8 부터 final생략 가능 
		//Iv=3; 값이 바뀌면  상수로 안되다 보니 밑에class에서 사용하지 못한다.
		
		class LocalInner{//지역 내부 클래스를 감싸고 있는 메소드의 상수만 사용가능 
			int liv = outerIv;
			int liv2 = outerCv;
			/* lv=3; */ //값이 바뀌지 않는 변수는 상수로 간주 
			//외부 클래스의 지역변수는 final이 붙은 변수 (상수)만 접근가능하다.
			int Iiv2 =Iv;//에러 !!! (JDK1.8 부터 에러아님)
			int Iiv4 =Lv;//OK
			
		   void method() {
			   
			   System.out.println(Iv);
			   //myMethod()와는 다른 메소드 이다 위에 메소드는 작업을 끝냈는데 이게 계속 돌아가면 위에
			   //변수를 사용할수가 없다 하지만 상수는 constant Pool이 따로 있어서 거기에 남아있어 가져오면된다. 
		   }
			
		}
		
	}
}
핵심
1) 외부 클래스의 private 멤버도 접근 가능하다.
2) 지역 변수 특징은 메소드 호출과 동시에 소멸된다 .
지역 메소드 클래스는 내부클래스의 객체가  지역메소드 내 지역 변수보다  더 오래 존재하기에  (상수)만 접근이 가능다, 하지만 최근에는 값이 변하지 않는 다면 그것을 상수라고 간주하고 final없이도 사용할 수 있다. 
package main1100;

public class Outer2 {
	class InstanceInner{
		
		int iv = 100;
	}

	static class StaticInner{
		int  iv =200;
		static int cv = 300;
		
	}
	
	void myMethod() {
		class LocalInner{
			int iv = 400;
			
		}
		
	}
}
package main1100;

public class Ex7_15 {
	public static void main(String[] args) {
		
		Outer2 oc = new Outer2();//외부 클래스의 인스턴스를 먼저 생성해야 인스턴스 클래스의 접근가능
		Outer2.InstanceInner ii = oc.new InstanceInner();// 인스턴스를 생성 가능
		
		System.out.println("ii.iv:" + ii.iv );
		System.out.println("Outer2.StaticInner.cv:" + Outer2.StaticInner.cv);
	
	
		///스태틱 내부 클래스의 인스턴스는  외부 클래스를 먼저 생성하지 않아도 된다.
		
		Outer2.StaticInner si = new Outer2.StaticInner();
		System.out.println("si.iv:" + si.iv);
		
	
	}
	
	
}

총 클래스 5개가 만들어진다.

package main1100;

public class Outer3 {
	int value = 10;
	
	class Inner{
		
		int value =20;
		
		void method1() {
			int value =30;
			System.out.println("    value:" + value); //30
			System.out.println("     this.value:" + this.value); //20
			System.out.println("Outer3.this.value:" + Outer3.this.value);//10
			
			
		}
		
	}//Inner클래스의 끝

}//Outer3클래스의 끝

class Ex7_16{
	public static void main(String[]args) {
		Outer3 outer = new Outer3();
		Outer3.Inner inner = outer.new Inner();
		 inner.method1();
		
	}
	
	
}

참조:https://www.youtube.com/watch?v=cZJyRGX2VoM