Java Class Notes

Inner Class(내부 클래스)

헤일리유 2023. 2. 24. 16:52

 

 

내부 클래스 (Inner Class)

 


 

 

 

내부 클래스란?

  • 클래스 안에 선언된 클래스
  • 특정 클래스 내에서만 주로 사용되는 클래스를 내부 클래스로 선언한다.
  • GUI어플리케이션(AWT, Swing)의 이벤트처리에 주로 사용된다.

 

 

 

 

내부 클래스의 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
  • 코드의 복잡성을 줄일 수 있다.(캡슐화)

 

 

 

 

내부 클래스의 종류와 특징

  • 내부 클래스의 종류는 변수의 선언위치에 따른 종류와 동일하다.
  • 유효범위와 성질도 변수와 유사하므로 비교해보면 이해하기 쉽다.
내부 클래스 ( Inner Class ) 특 징 ( Chacteristic )
인스턴스 클래스 ( Instance class ) 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 instance멤버처럼 다루어진다. 주로 외부 클래스의 instance멤버들과 관련된 작업에 사용될 목적으로 선언된다.
스테틱 클래스 ( Static class ) 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 sttatic멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다
지역 클래스 ( Local class ) 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
익명 클래스 ( Anonymous class ) 클래스의 선언과 객체의 생성을 동시에 하는 이름 없는 클래스 (일회용)

 

 

 

 

Inner Class

중첩(내부) 클래스 (Inner Class)

  • 클래스 내부에 또 다른 클래스를 가짐으로 클래스 관리의 효율을 높인 것(static 포함불가)

중첩 클래스의 형식과 생성파일

  • 형식) class Outer { class Inner { ... } }
  • 생성파일) Outer.class, Outer$Inner.class

중첩 클래스 객체 생성

  • Outer.Inner oi = new Outer().new Inner();

 

 

 

 

 

Ex

class 실행

package ch07;

public class Outer {
	private int height;
	private int width;
	public Outer(int height, int width) {
		this.height = height; this.width = width;
	}
	public Inner getInner() {
		return new Inner();
	}
	class Inner{	// Outer$Inner.class  //  컴파일시 이렇게 separate file로 저장된다 
		private float rate = 0.5f;
		public float capacity() {
			return rate * height * width;
		}
	}
}

실행

 

package ch07;

public class OuterEx {

	public static void main(String[] args) {
		Outer out = new Outer(100, 200);
//		Inner inner = new Inner();		// 이렇게 하면 이너 클래스를 못 찾고 에러남 
		Outer.Inner inner1 = out.new Inner();
		Outer.Inner inner2 = out.new Inner();

		System.out.println(inner1.capacity());
		System.out.println(inner2.capacity());
	}
}

result :

10000.0
10000.0

 

GUI ( Graphic User Interface ) 화면에서 주로 사용

 

 

 

 

 

 

 

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

  • 내부 클래스의 접근제어자는 변수에 사용할 수 있는 접근제어자와 동일하다
  • static클래스만 static멤버를 정의할 수 있다.

 

 

 

 

 

 

 

 


 

 

 

클래스간의 관계

 

 

포함관계(composite)

  • 한 클래스의 멤버변수로 다른 클래스를 선언하는 것
  • 작은 단위의 클래스를 먼저 만들고, 이 들을 조합해서 하나의 커다란 클래스를 만든다.

 

 

 

클래스간의 관계 설정하기 - 상속 vs 중첩

  • 가능한 한 많은 관계를 맺어주어 재사용성을 높이고 관리하기 쉽게 한다.
  • ‘is-a’와 ‘has-a’를 가지고 문장을 만들어 본다.

 

 

 

 

 

 

 

 

Ex - 포함관계

package ch07;

public class Engine {
	private int displacement;
	private String type;
	Engine() {}
	Engine (int displacement, String type) {
		this.displacement = displacement; this.type = type;
	}
	void print() {
		System.out.println("====================");
		System.out.println("displacement : "+displacement);
		System.out.println("type : "+type);
	}
}
package ch07;

public class Car2 {
	private Engine eg;	// 포함 : 다른 클래스(객체)를 멤버변수로 사용 
	private String color;
	Car2() {}
	Car2(Engine eg, String color) {
		this.eg = eg; this.color = color;
	}
	void print() {
		eg.print();
		System.out.println("color : "+color);
	}
}
package ch07;

public class Car2Ex {

	public static void main(String[] args) {
		Engine eg1 = new Engine(2000, "GDI");
		Engine eg2 = new Engine(1500, "DOHC");
		
		Car2 c1 = new Car2(eg1, "red");
		Car2 c2 = new Car2(eg1, "green");
		Car2 c3 = new Car2(eg2, "blue");
		
		c1.print();  c2.print();  c3.print();

	}
}

result :

====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue

 

위의 코드 보완

package ch07;

public class Car2Ex {

	public static void main(String[] args) {
		Engine eg1 = new Engine(2000, "GDI");
		Engine eg2 = new Engine(1500, "DOHC");
		
		Car2 c1 = new Car2(eg1, "red");
		Car2 c2 = new Car2(eg1, "green");
		Car2 c3 = new Car2(eg2, "blue");
		
		c1.print();  c2.print();  c3.print();
		
		System.out.println("- - - - - - - - - - - - - - - -");
		Car2[] car = {c1, c2, c3};
		for (int i=0; i<car.length;i++) {
			car[i].print();
		}
		System.out.println("- - - - - - - - - - - - - - - -");
		Car2[] cars = {c1, c2, c3};
		for (Car2 c:car) {
			c.print();
		}		
	}
}

result :

====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
- - - - - - - - - - - - - - - -
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
- - - - - - - - - - - - - - - -
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue

 

 

 

 

 


 

 

 

 

 

Ex - Apple Sale

seller

package ch07;

public class FruitSeller {
	
	int numberOfApple = 20;
	int money = 0;
	final int PRICE_PER_APPLE = 1000;
	
	int saleApple(int amt) {
		money += amt;
		int num = amt/PRICE_PER_APPLE;
		numberOfApple -= num;
		return num;
	}
	
	void print() {
		System.out.println("seller apple : "+numberOfApple);
		System.out.println("seller money : "+numberOfApple);
	}

}

buyer

package ch07;

public class FruitBuyer {
	int numberOfApple = 0;
	int money = 5000;
	void buyFruit (FruitSeller fs, int amt) {
		int num = fs.saleApple(amt);
		money-=amt;
		numberOfApple+=num;
	}
	void print() {
		System.out.println("buyer apple : "+numberOfApple);
		System.out.println("buyer money : "+money);
		System.out.println("=====================");
	}

ex

package ch07;

public class FruitEx {

	public static void main(String[] args) {
		FruitSeller fs1 = new FruitSeller();
		FruitSeller fs2 = new FruitSeller();
		FruitBuyer fb1 = new FruitBuyer();
		FruitBuyer fb2 = new FruitBuyer();
		FruitBuyer fb2 = new FruitBuyer();
		
		fb1.buyFruit(fs1, 3000);
		fb1.buyFruit(fs2, 2000);
		fb2.buyFruit(fs1, 2000);
		fs1.print();	fs2.print();
		fb1.print();	fb2.print();

	}

}

result

seller apple : 15
seller money : 15
seller apple : 18
seller money : 18
buyer apple : 5
buyer money : 0
=====================
buyer apple : 2
buyer money : 3000
=====================

 

 

 

 

Ex - Apple Sale 3

seller

package ch07;

public class FruitSeller3 {
	
	String name; int numberOfApple, money;
	final int PRICE_PER_APPLE = 1000;
	
	public FruitSeller3(String name, int numberOfApple, int money) {
		this.name = name; this.numberOfApple=numberOfApple; this.money = money;
	}
	int saleApple(int amt) {
		int num = amt/PRICE_PER_APPLE;
		if (numberOfApple>=num) {
			money += amt;
			numberOfApple -= num;
			System.out.printf("%s sold %d apple for %d won\n",name , num, amt);
		} else {
			System.out.println(name+" : sold out");
			num=0;
		}
		return num;
	}
	void print() {
		System.out.println(name+" apple : "+numberOfApple);
		System.out.println(name+" money : "+money);
		System.out.println("---------------------------");
	}
}

buyer

package ch07;

public class FruitBuyer3 {
	
	String name; int numberOfApple=0, money=5000; 
	
	public FruitBuyer3(String name, int money, int numberOfApple) {
		this.name = name; this.money = money; this.numberOfApple=numberOfApple;
	}
	void buyFruit(FruitSeller3 fs, int amt) {
		if (money<amt) {
			System.out.println(name+" : not enough money");
		}
		else {
			int num = fs.saleApple(amt);
			if (num !=0) {
				money -= amt;
				numberOfApple += num;
				System.out.printf("%s bought %d apple for %d won\n", name, num, amt);
			} else System.out.println(name+" : sold out? i'm disappointed");
		}
	}
	void print() {
		System.out.println(name+" apple : "+numberOfApple);
		System.out.println(name+" money : "+money);
		System.out.println("---------------------------");
		
	}

}

 

ex

package ch07;

public class FruitEx3 {

	public static void main(String[] args) {
		FruitSeller3 fs1 = new FruitSeller3("Cindy", 30, 1000);
		FruitSeller3 fs2 = new FruitSeller3("Teddy", 5, 0);
		FruitBuyer3 fb1 = new FruitBuyer3("Larry", 20000, 0);
		FruitBuyer3 fb2 = new FruitBuyer3("Penelope", 10000, 5);
		
		fb1.buyFruit(fs1, 3000);
		fb1.buyFruit(fs2, 2000);
		fb2.buyFruit(fs1, 12000);
		fb2.buyFruit(fs2, 5000);
		
		
		fs1.print();	fs2.print();
		fb1.print();	fb2.print();
	}

}

result :

Cindy sold 3 apple for 3000 won
Larry bought 3 apple for 3000 won
Teddy sold 2 apple for 2000 won
Larry bought 2 apple for 2000 won
Penelope : not enough money
Teddy : sold out
Penelope : sold out? i'm disappointed
Cindy apple : 27
Cindy money : 4000
---------------------------
Teddy apple : 3
Teddy money : 2000
---------------------------
Larry apple : 5
Larry money : 15000
---------------------------
Penelope apple : 5
Penelope money : 10000
---------------------------

 

 

 

 


 

 

참조변수의 형변환


 

 

참조변수의 형변환

  • 서로 상속관계에 있는 타입간의 형변환만 가능하다.
  • 자손 타입에서 조샅타입으로 형변환하는 경우, 형변환 생략가능
자손타입  -->  조상타입 (Up-casting)           :    형변환 생략 가능
자손타입  <--  조상타입 (Down-casting)      :    형변호나 생략 불가

 

 

 

 

 

instanceof 연산자

  • 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용.
  • 이항연산자이며 피연산자는 참조형 변수와 타입. 연산결과는 true, false.
  • instanceof의 연산결과가 true이면, 해당 타입으로 형변환이 가능하다.

 

public class Car2Ex2 {
	public static void main(String[] args) {
		FireEngine fe = new FireEngine(); Ambulance ab = new Ambulance(); Car2[] car = new Car2[2];
		car[0] = fe; car[1] = ab;
		for (Car2 c : car) {
			c.drive();	 // 부모에 있는 메소드만 실행 가능
            			// 실행되는 메소드는 자식 것
            // c.job();
			if (c instanceof FireEngine) {
			FireEngine fe2 = (FireEngine)c;
			fe2.job();
		}
	} 
}

 

 

 

 

참조변수와 인스턴스변수의 연결

  • 멤버변수가 중복정의된 경우, 참조변수의 타입에 따라 연결되는 멤버변수가 달라진다. (참조변수타입에 영향받음)
  • 메서드가 중복정의된 경우, 참조변수의 타입에 관계없이 항상 실제 인스턴스의 타입에 정의된 메서드가 호출된다.(참조변수타입에 영향받지 않음)

 

 

 

 

 

 

 

 

 

 

 

Ex 

package ch07;
public class Car3 {
	String color = "blue";
	void drive() {
		System.out.println("Lego!");
	}
}
class FireEngine3 extends Car3{
	String color = "red";
	void drive() {
		System.out.println("with lots of water");
	}
	void fire() {
		System.out.println("On way to fight the fire");
	}
}
class Ambulance3 extends Car3 {
	String color= "white";
	void drive() {
		System.out.println("got a patient");
	}
}
class Bus3 extends Car3 {
	void drive() {
		System.out.println("up to 45 people");
	}
}

>>

package ch07;
public class Car3Ex {
	public static void main(String[] args) {
//		부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적 
		Car3 car1 = new FireEngine3();
		Car3 car2 = new Ambulance3();
		Car3 car3 = new Bus3();
//		부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능  
//		실제로 실행되는 내용은 자식 메서드  
		car1.drive(); car2.drive(); car3.drive();  // car1.fire();
		System.out.println("====================");
		Car3[] cars = {car1, car2, car3};
		for (Car3 car:cars) {
			System.out.println(car.color);	// 변수는 부모의 값이 실행 
			car.drive();	// 메서드는 자식 메서드 실행 
		}
	}
}

result : 

with lots of water
got a patient
up to 45 people
====================
blue
with lots of water
blue
got a patient
blue
up to 45 people

>>>  변수는 부모의 값이 실행

>>>  메서드는 자식 메서드 실행 

 

package ch07;
public class Car3Ex {
	public static void main(String[] args) {
//		부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적 
		Car3 car1 = new FireEngine3();
		Car3 car2 = new Ambulance3();
		Car3 car3 = new Bus3();
//		부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능  
//		실제로 실행되는 내용은 자식 메서드  
		car1.drive(); car2.drive(); car3.drive();  // car1.fire();
		System.out.println("====================");
		Car3[] cars = {car1, car2, car3};
		for (Car3 car:cars) {
//			변수는 부모의 값이 실행, 변수는 이름은 같지만 다른 변수로 인식 
			System.out.println(car.color);	// 변수는 부모의 값이 실행 
			car.drive();	// 메서드는 자식 메서드 실행 
//			원래 FireEngine3였던 car는 에러가 발생하지 않지만 다른 경우에는 에러 발생  
			FireEngine3 fEngine3 = (FireEngine3)car;
			fe.fire();
		}
	}
}

> 아래 두 줄 에러 발생

package ch07;
public class Car3Ex {
	public static void main(String[] args) {
//		부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적 
		Car3 car1 = new FireEngine3();
		Car3 car2 = new Ambulance3();
		Car3 car3 = new Bus3();
//		부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능  
//		실제로 실행되는 내용은 자식 메서드  
		car1.drive(); car2.drive(); car3.drive();  // car1.fire();
		System.out.println("====================");
		Car3[] cars = {car1, car2, car3};
		for (Car3 car:cars) {
//			변수는 부모의 값이 실행, 변수는 이름은 같지만 다른 변수로 인식 
			System.out.println(car.color);	// 변수는 부모의 값이 실행 
			car.drive();	// 메서드는 자식 메서드 실행 
//			원래 FireEngine3였던 car는 에러가 발생하지 않지만 다른 경우에는 에러 발생  
//			FireEngine3 fEngine3 = (FireEngine3)car;
//			fe.fire();
			if (car instanceof FireEngine3)	// 현재 car가 FireEngine3에서 온 것인지 확인 
				((FireEngine3)car).fire();	// 두 줄을 한 줄로 간편하게 변경 
		}
	}
}

result :

with lots of water
got a patient
up to 45 people
====================
blue
with lots of water
On way to fight the fire
blue
got a patient
blue
up to 45 people

 

 

 

 

 


 

 

 

 

Ex

package ch07;
public class Animal {
	int x = 7;
	void move() {
		System.out.println("move");
	}
}
class Pig extends Animal {
	int x = 10;
	void move() {
		System.out.println("walk with 4 legs");
	}
}
class Bird extends Animal {
	void move() {
		System.out.println("fly with 2 wings");
	}
	void eat() {
		System.out.println("peck peck");
	}
}
class Fish extends Animal {
	void move() {
		System.out.println("swim with 2 fins");
	}
}
package ch07;

public class AnimalEx {

	public static void main(String[] args) {

		Animal[] animals = {new Pig(), new Bird(), new Fish()};

		for (Animal a:animals) {
			a.move();
			System.out.println("x = "+a.x);
			if (a instanceof Bird)
				((Bird)a).eat();
		}
			
	}

}

result :

walk with 4 legs
x = 7
fly with 2 wings
x = 7
peck peck
swim with 2 fins
x = 7

 

 

 

 


 

 

 

 

Ex

parent - Person2

package ch07;
public class Person2 {
	private String name;
	private int age;
	public Person2(String name, int age) {
		this.name = name; this.age = age;
	}
	void print() {
		System.out.println("==========================");
		System.out.println("Name : "+name);
		System.out.println("Age : "+age);
	}
}

childeren

package ch07;

public class Student2 extends Person2 {
	private String sno;
	public Student2(String name, int age, String sno) {
		super(name, age);
		this.sno=sno;
	}
	void print() {
		super.print();
		System.out.println("Student number : "+sno);
	}
}

class Teacher2 extends Person2 {
	private String subject;
	public Teacher2(String name, int age, String subject) {
		super(name, age); this.subject = subject;
	}
	void print() {
		super.print();
		System.out.println("Subject : "+subject);
	}
}

class Manager2 extends Person2 {
	private String part;
	public Manager2(String name, int age, String part) {
		super(name, age); this.part = part;
	}
	void print() {
		super.print();
		System.out.println("Part : "+part);
	}
}

ex - Person2Ex

package ch07;

public class Person2Ex {

	public static void main(String[] args) {
		Person2[] person = new Person2[6];
		person[0] = new Student2("rose", 26, "970201");
		person[1] = new Student2("jayden", 25, "960202");
		person[2] = new Teacher2("jennie", 27, "Art");
		person[3] = new Student2("derek", 32, "Music");
		person[4] = new Student2("Lisa", 34, "Accounting");
		person[5] = new Student2("Ben", 30, "Cleaning");
		
		for (Person2 p:person) {
			p.print();
		}
        
	}

}

result : 

==========================
Name : rose
Age : 26
Student number : 970201
==========================
Name : jayden
Age : 25
Student number : 960202
==========================
Name : jennie
Age : 27
Subject : Art
==========================
Name : derek
Age : 32
Student number : Music
==========================
Name : Lisa
Age : 34
Student number : Accounting
==========================
Name : Ben
Age : 30
Student number : Cleaning

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Java Class Notes' 카테고리의 다른 글

javaLang (주요 클래스)  (0) 2023.02.28
Interface (다형성&추상 메서드)  (1) 2023.02.27
Inheritance(상속)  (0) 2023.02.24
Access Modifier and Encapsulation (접근제어자와 캡슐화)  (0) 2023.02.23
Ex - OOP  (0) 2023.02.23