~홍~

Java _ InnerClass 13 본문

java/학원수업

Java _ InnerClass 13

~홍~ 2020. 12. 6. 18:39
728x90

Inner 01 

// 변수 선언:
// 1. 멤버 변수(필드) : 클래스에서 선언된 변수
//   - 클래스 내부 어느 곳에서나 사용할 수 있는 변수
//   - 수식어(public, private, static, ...)를 사용할 수 있음
// 2. 지역 변수 : 메소드 안에서 선언하는 변수
//   - 지역 변수가 선언된 곳에서부터 변수가 속한 블록이 끝나는 곳까지 사용할 수 있는 변수
//   - 접근 수식어(public, private, static, ...)를 사용할 수 없음
//   - final은 사용 가능

// 내부 클래스(Inner Class) : 다른 클래스 내부에서 정의된 클래스
// 1. 멤버 내부 클래스(member inner class)
//   - 멤버 변수를 선언하는 위치에서 정의하는 내부 클래스
//   - 외부 클래스의 인스턴스가 생성되어야만 객체 생성이 가능함
// 2. static 내부 클래스(static inner class), 중첩 클래스(nested class)
//   - 멤버 변수를 선언하는 위치에서 static으로 정의한 내부 클래스
//   - 외부 클래스의 인스턴스를 생성하지 않아도 객체 생성이 가능함
//   - 외부 클래스와 상관이 없는 클래스라고 생각해도 됨
// 3. 지역 내부 클래스(local inner class) : 메소드 안에서 정의하는 클래스
//  1) 이름이 있는 local class
//  2) 이름이 없는 local class : 익명 클래스(anonymous class)
//       -> 람다 표현식(lamdba expression)

public class OuterClass {
	// 멤버 변수
	private int value1;
	
	// 생성자
	public OuterClass(int v) {
		this.value1 = v;
	}
	
	// 메소드
	public void display() {
		System.out.println("value1 = " + value1);
	} // end display()
	
	// 멤버 내부 클래스(member inner class)
	class InnerClass {
		private int value2;
		
		public InnerClass(int v) {
			this.value2 = v;
		}
		
		// 외부 클래스의 멤버 변수는 내부 클래스에서 직접 사용이 가능
		public void setOuterValue(int value) {
			value1 = value;
		}
		
		public void printValues() {
			// 외부 클래스의 멤버 변수 출력
			System.out.println("outer value : " + value1);
			
			// 내부 클래스의 멤버 변수 출력
			System.out.println("inner value : " + value2);
		}
		
	} // end InnerClass
	
} // end OuterClass

Main 

public class InnerMain01 {
	private int x; // 멤버 변수
	
	public static void main(String[] args) {
		int y; // 지역 변수
		
		// 외부 클래스 OuterClass의 인스턴스를 생성
		OuterClass out1 = new OuterClass(100);
		out1.display();
		
		// 외부 클래스의 인스턴스를 생성했다고 해서
		// 내부 클래스의 인스턴스까지 생성된 것은 아님
		// -> 외부 클래스의 참조변수가 내부 클래스의 메소드를 사용할 수 없음
		
		// 내부 클래스의 인스턴스 생성:
		// (외부클래스 이름).(내부 클래스 이름) 변수이름 =
		//      (외부 클래스의 참조 변수).new (내부클래스 생성자)();
		OuterClass.InnerClass inner1 = out1.new InnerClass(200);
		inner1.printValues();
		
		System.out.println();
		// 내부 클래스의 인스턴스를 통한 외부 클래스 멤버변수 변경
		inner1.setOuterValue(300);
		inner1.printValues();
		out1.display();
		
		System.out.println();
		// out1 인스턴스를 통한 두번째 InnerClass 인스턴스 생성
		OuterClass.InnerClass inner2 = out1.new InnerClass(500);
		inner2.printValues();
		
	} // end main()
	
} // end InnerMain01

출력 

더보기

value1 = 100
outer value : 100
inner value : 200

outer value : 300
inner value : 200
value1 = 300

outer value : 300
inner value : 500


Inner 02

=> 멤버 내부 클래스(member inner class)

// 멤버 내부 클래스(member inner class)를 사용하는 경우:
// 상속관계로는 묶을 수 없지만,
// A라는 객체가 생성된 이후에만 존재할 수 있는 B라는 객체가 있다면
// B를 A의 내부 클래스로 정의
// (예) 자동차 - 타이어, PC - CPU/RAM 등

 

Car 

public class Car {
	private String name;
	
	public Car(String name) {
		this.name = name;
	}
	
	// 멤버 내부 클래스(member inner class)
	public class Tire {
		private int size;
		
		public Tire(int size) {
			this.size = size;
		}
		
		public void display() {
			System.out.println("--- 자동차 정보 ---");
			System.out.println("자동차 이름 : " + name);
			System.out.println("타이어 크기 : " + size);
		} // end display()
		
	} // end Tire
	
} // end Car

Main 

public class InnerMain02 {

	public static void main(String[] args) {
		// Car 인스턴스 및 Tire 인스턴스 생성 (2쌍)
		Car car1 = new Car("람보르기니");
		Car.Tire tire1 = car1.new Tire(20);
		tire1.display();
		
		System.out.println();
		Car car2 = new Car("K5");
		Car.Tire tire2 = car2.new Tire(15);
		tire2.display();

	} // end main()

} // end InnerMain02

출력 

더보기

--- 자동차 정보 ---
자동차 이름 : 람보르기니
타이어 크기 : 20

--- 자동차 정보 ---
자동차 이름 : K5
타이어 크기 : 15


Inner 03

 

외부 클래스 / 내부 클래스

// 외부 클래스
class OuterTest{
	private int value;
	public OuterTest(int value) {
		this.value = value;
	}
	public void printValue() {
		System.out.println("value = " + value);
	}
	
	// 멤버 내부 클래스
	class InnerTest {
		private int value;
		
		public InnerTest(int value) {
			this.value = value;
		}
		
		// 외부 클래스의 멤버 변수 이름과
		// 내부 클래스의 멤버 변수 이름이 같을 때
		// 외부 클래스의 멤버 변수를 참조하는 방법
		public void displayValues() {
			System.out.println("value = " + value);
			System.out.println("this.value = " + this.value);
			System.out.println("OuterTest.this.value = " + 
						OuterTest.this.value);
		}
		
	} // end InnerTest
	
} // end OuterTest

Main 

public class InnerMain03 {

	public static void main(String[] args) {
		// OuterTest 클래스의 인스턴스 생성
		OuterTest out = new OuterTest(100);
		out.printValue();
		
		System.out.println();
		OuterTest.InnerTest inner = out.new InnerTest(200);
		inner.displayValues();

	} // end main()

} // end InnerMain03

출력 

더보기

value = 100

value = 200

this.value = 200

OuterTest.this.value = 100


Inner 04

 

외부 클래스 / 내부 클래스

// 외부 클래스
class OuterClass {
	int value;
	static int count = 0;
	public OuterClass(int value) {
		this.value = value;
	}
	
	// static 내부 클래스(중첩 클래스, nested class)
	static class NestedClass {
		private String name;
		
		public NestedClass(String name) {
			this.name = name;
		}
		
		public void display() {
//			System.out.println("value = " + value);
			// 외부 클래스의 static이 아닌 변수는 참조할 수 없음!
			
			System.out.println("count = " + count);
			// 외부 클래스에서 static으로 선언된 변수는 참조 가능
			
			System.out.println("name = " + name);
		} // end display()
		
	} // end NestedClass
	
} // end OuterClass

 Main 

public class InnerMain04 {

	public static void main(String[] args) {
		// static 멤버 변수 사용 : (클래스이름).(변수이름)
		OuterClass.count = 100;
		System.out.println(OuterClass.count);
		
		// 중첩 클래스(static 클래스)
		// (외부클래스 이름).(중첩클래스 이름) 변수이름 =
		// 		new (외부클래스 이름).(내부클래스 이름)();
		OuterClass.NestedClass nest = 
				new OuterClass.NestedClass("Peter");
		nest.display();

	} // end main()

} // end InnerMain04

출력  

더보기

100
count = 100
name = Peter


Inner 05

 

외부클래스 

class OuterClass {
	private int value;
	
	public OuterClass(int value) {
		this.value = value;
	}
	
	public void test() {
		int x = 123; // 지역 변수(local variable)
		
		// 지역 변수를 선언하는 위치에서 정의하는 클래스 : 지역 클래스
		class LocalClass {
			private int value2; // 지역클래스의 멤버 변수
			
			// 지역 클래스의 생성자
			public LocalClass(int value2) {
				this.value2 = value2;
			}
			
			// 지역 클래스의 메소드
			public void display() {
				// 외부 클래스의 멤버 변수를 참조 가능
				System.out.println("value = " + value);
				
				// 메소드의 지역 변수 사용 가능
				System.out.println("x = " + x);
				
				// 지역 클래스의 멤버 변수를 참조 가능
				System.out.println("value2 = " + value2);
			} // end display()
			
		} // end LocalClass
		
		// 지역 클래스의 인스턴스 생성 - 메소드 안에서만 가능
		LocalClass local = new LocalClass(1234);
		local.display();
		
	} // end test()
	
} // end OuterClass

Main 

public class InnerMain05 {

	public static void main(String[] args) {
		OuterClass outer = new OuterClass(100);
		outer.test();
	} // end main()

} // end InnerMain05

출력 

더보기

value = 100
x = 123
value2 = 1234


Inner 06

 

Person 

class Person {
	private String name; // 멤버 변수
	
	// 생성자
	public Person(String name) {
		this.name = name;
	}
	
	// 메소드
	public PersonInterface setAge(int age) { // 리턴 타입 : PersonInterface
		// 지역 클래스 정의
		class PersonWitAge implements PersonInterface {
			private int age; // 지역 클래스의 멤버 변수
			
			public PersonWitAge(int age) {
				this.age = age;
			}

			@Override
			public void showInfo() {
				System.out.println("이름 : " + name);
				System.out.println("나이 : " + age);				
			}

			@Override
			public void hello() {
				System.out.println("안녕하세요!");
			}
			
		} // end PersonWithAge
		
		// 지역 클래스 객체(내용)을 모두 저장
		PersonWitAge instance = new PersonWitAge(age);
		
		// 지역 클래스 객체(내용)을 리턴
		return instance;
		
	} // end setAge()
	
} // end Person

 PersonInterface

interface PersonInterface {
	public abstract void showInfo();
	
	public abstract void hello();
} // end PersonInterface

Main 

public class InnerMain06 {

	public static void main(String[] args) {
		// 지역 클래스의 메소드들을 외부에서 사용하는 방법 :
		// 1. 지역 클래스의 메소드들을 선언한 인터페이스를 정의
		// 2. 지역 클래스가 인터페이스를 구현하도록 정의
		// 3. 다형성을 사용하여 메소드의 리턴타입으로 인터페이스를 사용할 수 있음
		
		Person p = new Person("목쌤");
		PersonInterface instance = p.setAge(20);
		instance.showInfo();
		instance.hello();

	} // end main()

} // end InnerMain06

출력 

더보기

이름 : 목쌤
나이 : 20
안녕하세요!


Inner 07

 

interface Hello {
	public abstract void hello();
} // end Hello

class Person implements Hello {
	@Override
	public void hello() {
		System.out.println("안녕?");		
	}
} // end Person

class Dog implements Hello {
	@Override
	public void hello() {
		System.out.println("멍멍");
	}
} // end Dog

Main

public class InnerMain07 {

	public static void main(String[] args) {
		Person p1 = new Person(); // 원래 형태1
		p1.hello();
		
		Hello p2 = new Person(); // 원래 형태2
		p2.hello();
		
		Hello dog = new Dog(); // 원래 형태3
		dog.hello();
		
		// 익명 클래스
		Hello cat = new Hello() {
			@Override
			public void hello() {
				System.out.println("냐옹");
			}	
		};
		cat.hello();
		
		Hello father = new Hello() {
			@Override
			public void hello() {
				System.out.println("I'm your father");			
			}
		};
		// new Hello() { 본체 }
		// 본체 : Hello interface를 구현하는 클래스의 내용(객체)
		father.hello();

	} // end main()

} // end InnerMain07

출력 

더보기

안녕?
안녕?
멍멍
냐옹
I'm your father


Inner 08

 

Button

public class Button {
	// 내부 인터페이스
	public interface OnClickListener {
		public abstract void onClick();
	}
	
	private OnClickListener listener;
	
	public void setOnClickListener(OnClickListener listener) {
		this.listener = listener;
	}
	
	public void click() {
		listener.onClick();
	}
	
} // end Button

FinishListener

class FinishListener implements Button.OnClickListener {

	@Override
	public void onClick() {
		System.out.println("<<< 종료 >>>");
	}
	
} // end FinishListener

class CancelListener implements Button.OnClickListener {

	@Override
	public void onClick() {
		System.out.println("<<< 취소 >>>");		
	}
	
} // end CancelListener

Main 

public class InnerMain08 {

	public static void main(String[] args) {
		Button btnFinish = new Button();
		
		Button.OnClickListener finListener = new FinishListener(); // 다형성
		
		btnFinish.setOnClickListener(finListener);
		btnFinish.click();
		
		System.out.println();
		Button btnCancel = new Button();
//		Button.OnClickListener cancel = new CancelListener();
		btnCancel.setOnClickListener(new CancelListener());
		btnCancel.click();
		
		// 1. Button 객체 생성 : 이름 btn
		// 2. 익명 클래스를 사용하여 listener 객체 생성(onClick 메소드를 오버라이드 하여 사용)
		// 3. btn에 listener 적용(setOnclickListener())
		// 4. btn click() 메소드 호출
		System.out.println();
		Button btn = new Button();
		Button.OnClickListener l = new Button.OnClickListener() { // 익명 클래스 사용
			@Override
			public void onClick() {
				System.out.println("테스트");				
			}
		};
		btn.setOnClickListener(l);
		btn.click();
		
		btn.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick() {
				System.out.println("테스트2");
				
			}
		});
		btn.click();
		// 익명클래스를 사용하는 이유
		// - 인터페이스의 메소드가 한 개인 경우,
		//    클래스를 외부에서 선언하여 implements하지 않고 사용하기 위해
		// - 익명 클래스를 사용하면 클래스를 외부에서 생성할 필요가 없음

	} // end main()

} // end InnerMain08

출력 

더보기

<<< 종료 >>>

<<< 취소 >>>

테스트
테스트2

 

'java > 학원수업' 카테고리의 다른 글

Java _ Exception 15  (0) 2020.12.06
Java _ Lambda 14  (0) 2020.12.06
Java _ Collection 12  (0) 2020.12.06
Java _ API 11  (0) 2020.12.06
JAVA _ Interface 10  (0) 2020.12.06
Comments