본문 바로가기

BackEnd/Java

[java] 이것이 자바다 ch09 중첩 선언

728x90
반응형

1. 중첩 클래스

   ▷ 클래스 내부에 선언한 클래스

   ▷ 클래스의 멤버를 쉽게 사용할 수 있고 외부에는 중첩 관계 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있습니다.

   ▷ 멤버 클래스 : 클래스 멤버로서 선언되는 중첩 클래스

   ▷ 로컬 클래스 : 메소드 내부에서 선언되는 중첩 클래스

 

NO 선언 위치에 따른 분류 선언 위치 객체 생성 조건
1 멤버 클래스 인스턴스
멤버 클래스
class A {
   class B { ... }
}
A 객체를 생성해야만
B 객체를 생성할 수 있습니다.
2 정적
멤버 클래스
class A {
   static class B { ... }
}
A 객체를 생성하지 않아도
B 객체를 생성할 수 있습니다.
3 로컬 클래스 class A {
   void method() {
      static class B { ... }
   }
}
method가 실행할 때만
B 객체를 생성할 수 있습니다.

 

 

2. 인스턴스 멤버 클래스

   ▷ A 클래스의 멤버로 선언된 B클래스

[public] class A {
	[public | private] class B {
    }
}


1. public class B { } : 다른 패키지에서 B 클래스를 사용할 수 있다.
2. class B { } : 같은 패키지에서만 B 클래스를 사용할 수 있다.
3. private class B { } : A 클래스 내부에서만 B 클래스를 사용할 수 있다.

   ▷ 인스턴스 멤버 클래스 B는 주로 A클래스 내부에서 사용되므로 private 접근 제한을 갖는 것이 일반적입니다.

 

◎ 예제

1. A 클래스
public class A {
	// 인스턴스 멤버 클래스
	class B {}
	
	// 인스턴스 필드 값으로 B 객체 대입
	B field = new B();
	
	// 생성자
	A(){
		B b = new B();
	}
	
	// 인스턴스 메소드
	void method() {
		B b = new B();
	}
}​


2. AExample 메인 클래스

public class AExample {
	
	public static void main(String[] args) {
		
		// A 객체 생성
		A a = new A();
		
		// B 객체 생성
		A.B b = a.new B();	
	}
}


A 클래스 내부의 B 클래스를 사용하기 위해서는 [ A.B b = a.new B() ] 와 같은 형태로 사용해야합니다.

 

◎ 인스턴스 예제

1. A클래스
public class A {
	// 인스턴스 멤버 클래스
	class B {
		// 인스턴스 필드
		int field1 = 1;
		
		// 정적 필드(Java 17부터 허용)
		static int field2 = 2;
		
		// 생성자
		B(){
			System.out.println("B-생성자 실행");
		}
		
		// 인스턴스 메소드
		void method1() {
			System.out.println("B-method1 실행");
		}
		
		// 정적 메소드(Java 17부터 허용)
		static void method2() {
			System.out.println("B-method2 실행");
		}
	}
	
	// 인스턴스 메소드
	void useB() {
		// B 객체 생성 및 인스턴스 필드 및 메소드 사용
		B b = new B();
		System.out.println(b.field1);
		b.method1();
		
		// B 클래스의 정적 필드 및 메소드 사용
		System.out.println(B.field2);
		B.method2();
	}
}​

 

2. AExample 메인 클래스
public class AExample {
	
	public static void main(String[] args) {
		
		// A 객체 생성
		A a = new A();
		
		// A 인스턴스 메소드 호출
		a.useB();
	}
}

//	출력 :
//	B-생성자 실행
//	1
//	B-method1 실행
//	2
//	B-method2 실행​

 

 

3. 정적 멤버 클래스

   ▷ static 키워드와 함께 A 클래스의 멤버로 선언된 B 클래스

[public] class A {
	[public | private] static class B {
    }
}


1. public static class B { } : 다른 패키지에서 B 클래스를 사용할 수 있다.
2. static class B { } : 같은 패키지에서만 B 클래스를 사용할 수 있다.
3. private static class B { } : A 클래스 내부에서만 B 클래스를 사용할 수 있다.

   ▷ 정적 멤버 클래스는 주로 default 또는 public 접근 제한을 가집니다.

 

◎ 정적 메소드 예제

1. A 클래스
public class A {
	// 정적 멤버 클래스
	static class B{}
	
	// 인스턴스 필드 값으로 B 객체 대입
	B field1 = new B();
	
	// 정적 필드 값으로 B 객체 대입
	static B field2 = new B();

	// 생성자
	A(){
		B b = new B();
	}
		
	// 인스턴스 메소드
	void method1() {
		B b = new B();
	}
	
	// 정적 메소드
	static void method2() {
		B b = new B();
	}
}​


2. AExample 메인 클래스

public class AExample {
	
	public static void main(String[] args) {
		// B 객체 생성
		A.B b = new A.B();	
	}
}


위의 코드는 JAVA 8에서도 사용 가능합니다.

 

◎ 정적 메소드 예제2

1. A 클래스
public class A {
	// 인스턴스 멤버 클래스
	static class B {
		// 인스턴스 필드
		int field1 = 1;
		
		// 정적 필드(Java 17부터 허용)
		static int field2 = 2;
		
		// 생성자
		B(){
			System.out.println("B-생성자 실행");
		}
		
		// 인스턴스 메소드
		void method1() {
			System.out.println("B-method1 실행");
		}
		
		// 정적 메소드(Java 17부터 허용)
		static void method2() {
			System.out.println("B-method2 실행");
		}
	}
}​


2. AExample 메인 클래스
public class AExample {
	
	public static void main(String[] args) {
		
		// B 객체 생성 및 인스턴스 필드 및 메소드 사용
		A.B b = new A.B();
		System.out.println(b.field1);
		b.method1();
		
		// B 클래스의 정적 필드 및 메소드 사용
		System.out.println(A.B.field2);
		A.B.method2();
	}
}

//	출력 : 
//	B-생성자 실행
//	1
//	B-method1 실행
//	2
//	B-method2 실행​

 

 

4. 로컬 클래스

   ▷ 생성자 또는 메소드 내부에서 다음과 같이 선언된 클래스

   ▷ 생성자와 메소드가 실행될 동안에만 객체를 생성할 수 있습니다.

[public] class A{
	// 생성자
	public A(){
    	class B { }  // 로컬 클래스
    }
    
    // 메소드
	public void method(){
    	class B { }   // 로컬 클래스
    }
}

 

◎ 예제

1. A 클래스
public class A {
	// 메소드
	void useB() {
		// 로컬 클래스
		class B{
			// 인스턴스 필드
			int field1 = 1;
			
			// 정적 필드(Java 17부터 허용)
			static int field2 = 2;
			
			//생성자
			B() {
				System.out.println("B-생성자 실행");
			}
			
			// 인스턴스 메소드
			void method1() {
				System.out.println("B-method1 실행");
			}
			
			// 정적 메소드(Java 17부터 허용)
			static void method2() {
				System.out.println("B-method2 실행");
			}
		}
		
		// 로컬 객체 생성
		B b = new B();
		
		// 로컬 객체의 인스턴스 필드와 메소드 사용
		System.out.println(b.field1);
		b.method1();
		
		// 로컬 클래스의 정적 필드와 메소드 사용(JAVA 17부터 허용)
		System.out.println(B.field2);
		B.method2();
	}
}​

 

2. AExample 클래스
public class AExample {
	public static void main(String[] args) {
		
		// A 객체 생성
		A a = new A();
		
		// A 메소드 호출
		a.useB();
	}
}

//	출력 : 
//	B-생성자 실행
//	1
//	B-method1 실행
//	2
//	B-method2 실행​

 

◎ 로컬 변수

   ▷ 로컬 클래스에서 사용할 경우 로컬 변수는 final 특성을 갖게 되므로 값을 읽을 수만 있고 수정할 수 없게됩니다.

   ▷ 로컬 클래스 내부에서 값을 변경하지 못하도록 제한하기 때문입니다.

   ▷ Java 8 이후부터는 명시적으로 final을 붙이지 않아도 되지만 이전 버전에서는 붙여야합니다!!

 

1. A 클래스
public class A {
	// 메소드
	public void method1(int arg) { // final int age
		// 로컬 변수
		int var = 1;
		
		// 로컬 클래스
		class B{
			// 메소드
			void method2() {
				// 로컬 변수 읽기
				System.out.println("arg: " + arg);
				System.out.println("var: " + var);
				
				// 로컬 변수 수정
				// arg = 2;
				// var = 2;
			}
		}
		
		// 로컬 객체 생성
		B b = new B();
		
		// 로컬 객체 메소드 호출
		b.method2();
		
		// 로컬 변수 수정
		// arg = 3;
		// var = 3;
	}
}​


2. AExample 메인 클래스

public class AExample {
	
	public static void main(String[] args) {
		// B 객체 생성
		A a = new A();
		
		a.method1(2);
		
	}
}

//	출력 : 
//	arg: 2
//	var: 1

 

클래스 내부에 클래스를 만들어서 사용하는 방법에 대해서 배워보았습니다.

 

이렇게 사용하는 이유는 메모리에 데이터 공간을 많이 남기지 않기 위해서입니다.

 

요즘은 많은 양의 데이터를 다루기 때문에 데이터 공간을 확보하는 것이 중요합니다!

 

많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

 

728x90
반응형