본문 바로가기
ICIA 수업일지

2021.06.23 수업일지

by 주성씨 2021. 6. 26.

- 전화번호부 4단계

틀)

class PhoneInfo
{
	private String name;      //재활용
	private String phoneNum;  //재활용
	//생성자......
	public void showPhoneInfo(){ //오버라이딩: 재정의
		System.out.println("name="+name);
		System.out.println("phoneNum="+phoneNum);
	}
}

class PhoneUnivInfo   : 대학 친구들의 전화번호 저장
  *이름 : String name
  *전화번호 : String phoneNum
  *전공: String major
  *학년: int year

class PhneCompanyInfo   : 회사 동료들의 전화번호 저장
  *이름 : String name
  *전화번호 : String phoneNum
  *회사 : String company

예시)

// 실행 예

메뉴를 선택하세요.
----------------
1.데이터 입력
2.데이터 검색
3.데이터 삭제
4.데이터 전체 출력
5.프로그램 종료
----------------
선택: 1
데이터 입력을 시작합니다.
1.일반, 2.대학, 3.회사
선택>>1
이름: 홍길동
전화번호: 111-1111
데이터 입력이 완료되었습니다.

메뉴를 선택하세요.
----------------
1.데이터 입력
2.데이터 검색
3.데이터 삭제
4.프로그램 종료
----------------
선택:1
데이터 입력을 시작합니다.
1.일반, 2.대학, 3.회사
선택>>2
이름: 이순신
전화번호: 222-2222
전공: 컴퓨터공학
학년: 3
데이터 입력이 완료되었습니다.

메뉴를 선택하세요.
----------------
1.데이터 입력
2.데이터 검색
3.데이터 삭제
4.프로그램 종료
----------------
선택:1
데이터 입력을 시작합니다.
1.일반, 2.대학, 3.회사
선택>>3
이름: 갑돌이
전화번호: 333-3333
회사: ICIA
데이터 입력이 완료되었습니다.

ㄴ 기존 전화번호부에 넣어서 적용해보자.


- 추상 클래스(abstract class)

+ abstract?

package ex2;

public abstract class Employee // 근로자
{
	private String name;

	public Employee(String name) {
		this.name = name;
	}
	public void showYourName() {
		System.out.println("이름:" + name);
	}
    //오버라이딩 대상
	public int getPay() {
		return 0;
	}
	public void showSalaryInfo() {
	}
}

ㄴ 추상 클래스는 인스턴스 생성 불가

package ex2;  //소스에 가장 상단에 1번만 선언가능

public class Main
{
	public static void main(String[] args){
		// 직원관리를 목적으로 설계된 컨트롤 클래스의 인스턴스생성
		EmployeeHandler handler=new EmployeeHandler(100);  //제어 클래스(코딩어렵다)
		//정규직 등록
		handler.addEmployee(new Employee("KIM"));  //실수-->에러
		handler.addEmployee(new PermanentWorker("LEE", 1500));

ㄴ "handler.addEmployee(new Employee("KIM"));"  정규직 비정규직 영업직과 같은 명확한 게 필요하지 직원과 같은 추상적인 인스턴스는 불가능하다.

※ 추상 클래스(abstract class)란?
1. 클래스가 설계도라면 추상 클래스는 '미완성 설계도'이다.
2. 추상 메서드(미완성 메서드)를 포함하고 있는 클래스
3. 추상메서드 : 선언부만 있고 구현부가 없는 메서드
4. 하나 이상의 abstract메서드를 포함하는 클래스는 abstract로 선언되어야 하며, 인스턴스 생성은 불가능하다.
5. 인스턴스 생성은 불가능 하나, 참조 변수 선언은 가능하고, 오버 라이딩의 원리 그대로 적용됨.
6. 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우에 사용

+ 그렇다면 임플로이 클래스의 메서드는 다음과 같이 설정이 가능하다.

이전)

	public int getPay() {
		return 0;
	}
	public void showSalaryInfo() {
	}

이후)

	abstract public int getPay();
	abstract public void showSalaryInfo();

ㄴ 이를 추상 메서드라고 명칭 한다.
ㄴ 이 추상 메서드를 누가 완성하는 걸까?
ㄴ 각 하위 클래스가 오버 라이딩을 하여 완성한다. 다음과 같다.

package ex2;
//데이터 클래스
public class PermanentWorker extends Employee // 정규직
{
	@Override
	public int getPay() {
		return salary;//*12-세금..;
	}
	@Override
	public void showSalaryInfo() {
		showYourName();  //이름
		System.out.println("정규직 급여:" + getPay());
	}
package ex2;

public class SalesWorker extends PermanentWorker {
	@Override
	public int getPay(){
		return super.getPay()+(int)(salesResult*bonusRatio);
	}
	@Override
	public void showSalaryInfo() {
		showYourName();
		System.out.println("영업직 급여: " + getPay());
	}

+ 인터페이스(interface); 100% 추상 클래스

- 인터페이스는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이다. 즉, 사용자가 기기를 쉽게 동작시키는데 도움을 주는 시스템을 의미한다.(참고 wiki)

인터페이스 개요

예제)

package ex1;
// 일종의 클래스이기떄문에 대문자로 명명
public interface Test {
	// 일반적으로 추상메서드만 와야하기때문에 오류가 난다.
	public void show {
		System.out.println("test");
	}
	
}

ㄴ 이를 다음과 같이 바꿔야 한다.

package ex1;
// 일종의 클래스이기떄문에 대문자로 명명
public interface Test {
	// 일반적으로 추상메서드만 선언가능
	abstract public void show();
}

ㄴ 인터페이스는 추상 클래스이다.

package ex1;
// 일종의 클래스이기떄문에 대문자로 명명
// 인터페이스의 모든 메서드는 추상메서드 이다.
public interface Test {
	// 일반적으로 추상메서드만 선언가능
	abstract public void input();
	abstract public void output();
}

ㄴ 생략 가능한 부분도 있다.

package ex1;
// 일종의 클래스이기떄문에 대문자로 명명
// 인터페이스의 모든 메서드는 추상메서드 이다.
public interface Test {
	// 일반적으로 추상메서드만 선언가능
	abstract public void input(); //abstract를 넣어도 되지만
	public void output(); // 생략도 가능하다. 하지만 가독성을 위해서 퍼블릭은 넣자.

}

ㄴ 무조건 생략은 가독성을 낮춘다. Test 인터페이스를 추상 클래스로도 만들 수 있지만 abstract를 매번 기입해야 하기 때문에 추천하지는 않는다.

예제)

package aTeam;

import ex1.Test;

public class AMain implements Test {

	@Override
	public void input() {
		System.out.println("모니터로 출력 구현");
	}

	@Override
	public void output() {
		System.out.println("키보드로 입력");
	}
	
}

ㄴ Test 클래스를 ex1 패키지에서 임포트하고
ㄴ Test 패키지의 추상 메서드를 오버 라이딩한다.
ㄴ 둘 중의 하나라도 오버 라이딩하지 않으면 오류가 난다.

+ 회사라 가정하고 ex1패키지에 메인 클래스를 생성한다.

package ex1;

public class Main {
	// 팀장 작업
	public static void main(String[] args) {

	}

}

ㄴ 이를 다음과 같이 코딩한다.

package ex1;

import aTeam.AMain;

public class Main {
	// 팀장 작업
	public static void main(String[] args) {
		// 조상 타입 참조변수는 후손 인스턴스를 참조할 수 있다.
		Test a = new AMain();
		a.input(); //재정의
		a.output(); //재정의
		
	}

}

ㄴ Test 인터페이스는 AMain의 조상 클래스 이기 때문에 input output을 참조할 수 있으며 Test 인터페이스의 추상 메서드를 오버 라이딩할 수 있다.

※ 메서드 오버 라이딩 과정에서의 접근제어 지시자
- 메서드를 오버 라이딩 하는 과정에서 접근의 허용범위를 좁히는 방식으로는 접근제어 지시자를 변경 할 수 없다.
- 메소드 오버라이딩 과정에서 접근제어 지시자는 그대로 유지를 하는 것이 일반적이다.
- 상위 클래스의 public 메서드는 하위 클래스에서 오로지 public으로만 메서드를 오버 라이딩해야 한다.
- 상위 클래스에서 private 메서드는 하위 클래스에서 default, protected, public 으로 오버 라이딩 가 능하다.

※ 인터페이스는 둘 이상에 구현 가능하다.
- 클래스에서 인터페이스의 상속은 extends가 아닌 implements를 사용한다.

※ 인터페이스 간 상속도 가능하다.
- 단 이때는 implements가 아닌 extends를 사용한다.
ㄴ 별로 사용하지는 않는다.

※ interface 기반의 상수 표현
- 인터페이스 내에 선언된 변수는 무조건 public static final로 선언이 되므로, 이 둘은 완전 히 동일한 의미를 갖는다. ㄷex) interface Week { int MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7; }


참고. 전화번호부에 인터페이스를 넣어 스위치 함수 수정해보기

package phonebook;

public interface INIT_MENU {

	static final int INPUT=1;
	static final int SEARCH=2;
	static final int DELETE=3;
	static final int SHOWLIST=4;
	static final int EXIT=5;
	
}
		int menuNum;
		while(true) {
			showMenu();
			menuNum=sc.nextInt();
			switch(menuNum) {
			case INIT_MENU.INPUT:
				manager.inputData();
				break;
			case INIT_MENU.SEARCH:
				manager.searchData();
				break;
			case INIT_MENU.DELETE:
				manager.deleteData();
				break;
			case INIT_MENU.SHOWLIST:
				manager.showList();
				break;
			case INIT_MENU.EXIT:
				System.out.println("프로그램 종료");
				return;  //System.exit(0);
			}

ㄴ 위와 같이 나타내면 조금 길지만 가독성은 좋다.


- 인터페이스의 또 다른 가치

- 무엇인가를 표시하는(클래스의 특성을 표시하는) 용도로도 인터페이스는 사용된다.
- 이러한 경우, 인터페이스의 이름은  ~ able로 끝나는 것이 보통이며 비어 있을 수도 있다.
- Instanceof 연산자를 통해서 클래스의 특성을 파악할 수 있다.
- 인터페이스 UpperCasePrintable을 구현하는 클래스의 인스턴스가 print 메서드의 인자로 전달되면 문자열을 전부 대문자로 출력한다.

예제)

메인 클래스)

package ex2;

public class InterfaceMark {

	public static void main(String[] args) {

		PointOne pos1 = new PointOne(1, 1);
		PointTwo pos2 = new PointTwo(2, 2);
		PointOne pos3 = new PointOne(3, 3);
		PointTwo pos4 = new PointTwo(4, 4);
		ClassPrinter.print(pos1);
		ClassPrinter.print(pos2);
		ClassPrinter.print(pos3);
		ClassPrinter.print(pos4);
	}
}

인터페이스)

package ex2;

public interface UpperCasePrintable {
	// 대문자로 프린트가 가능한.
	// ~able로 끝나는 인터페이스들은 내용이 비어 있다.
	// 비어 있음
}

프린터 클래스)

package ex2;

public class ClassPrinter {
	public static void print(Object obj) {// 모든 클래스의 1대 조상
		String org = obj.toString();
		if (obj instanceof UpperCasePrintable) {
			org = org.toUpperCase();
		}
		System.out.println(org);
	}
}

하위 클래스 1)

package ex2;

public class PointOne implements UpperCasePrintable {
	private int xPos, yPos;

	PointOne(int x, int y) {
		xPos = x;
		yPos = y;
	}

	public String toString() {
		String posInfo = "[x pos:" + xPos + ", y pos:" + yPos + "]";
		return posInfo;
	}
}

하위 클래스 2)

package ex2;

public class PointTwo {
	private int xPos, yPos;

	PointTwo(int x, int y) {
		xPos = x;
		yPos = y;
	}

	public String toString() {
		String posInfo = "[x pos:" + xPos + ", y pos:" + yPos + "]";
		return posInfo;
	}
}

- 전화번호부 4단계 다시한번 해보기..


- 예외처리(Exception Handling)

1. 프로그램 오류와 예외 처리
▶ 컴파일 에러(compile-time error)와 런타임 에러(runtime error)
- 컴파일 에러 - 컴파일할 때 발생하는 에러 - 런타임 에러 - 실행할 때 발생하는 에러

▶ Java의 런타임 에러 - 에러(error)와 예외(exception)
- 에러(error)는 어쩔 수 없지만, 예외(exception)는 처리해야 한다.

2. try~catch문
- try 영역에서 발생한 예외상황은 이어서 등장하는 catch 영역에서 처리한다.
- 처리할 문장이 단문이라도 중괄호{} 를 생략해서는 안된다.

예시)

try {
/* 예외 발생 가능 지역 */
}
catch(처리 되어야 할 예외의 종류) {
/* 예외를 처리하는 코드 */
}

예문1)

package ex3;

public class Ex1_0623 {
	public static void main(String[] args) {
		try {
			System.out.println(4 / 0);
		} catch (ArithmeticException ex) { // 예외 전문 클래스
			System.out.println(ex.getMessage());
			System.out.println("0으로 나눌 수 없습니다.");
		}
	} //main end
} // class end

결과1)

/ by zero
0으로 나눌 수 없습니다.

 

예문2)

package ex3;

import java.util.Scanner;

public class Ex1_0623 {
	public static void main(String[] args) {
		System.out.print("두 개의 정수 입력: ");
		Scanner keyboard = new Scanner(System.in);
		int num1 = keyboard.nextInt();
		int num2 = keyboard.nextInt();
		try {
			System.out.println("나눗셈 결과의 몫: " + (num1 / num2));
			System.out.println("나눗셈 결과의 나머지: " + (num1 % num2));
		} catch (ArithmeticException e) // 예외 클래스 ArithmeticException
		{
			System.out.println("나눗셈 불가능");
			System.out.println(e.getMessage());
		}
		System.out.println("프로그램을 종료합니다.");
	}
} // class end

결과2)

두 개의 정수 입력: 10 0
나눗셈 불가능
/ by zero
프로그램을 종료합니다.

3. try 블록의 구성시 주의점
- try문 내에서 예외상황이 발생하고 처리된 다음에는, 나머지 try문을 건너띄고, try-catch의 이후를 실행한다는 특징으로 인해서 트랜잭션(Transaction)의 구성이 용이하다.

4. e.getMassage() 메서드
- ArithmaticException 클래스와 같이 예외상황을 알리기 위해 정의된 클래스를 가리켜 예외 클래스라 한다.
- 모든 예외클래스는 Throwable클래스를 상속하며, 이 클래스에는 getMassage메서드가 정의되어 있다.
- getMassage 메서드는 예외가 발생한 원인정보를 문자열의 형태로 반환된다.

5. 대표적인 예외 클래스
- 모든 경우에 있어서 예외로 인정되는 상황을 표현하기 위한 예외 클래스는 대부분 정의가 되어 있다. 그리고 프로그램에 따라서 별도로 표현해야 하는 예외상황에서는 예외 클래스를 직접 정의하면된다.

ArrayIndexOutOfBoundsException: 배열의 접근에 잘못된 인덱스 값을 사용하는 예외상황
ClassCastException: 허용할 수 없는 형변환 연산을 진행하는 예외상황
NegativeArraySizeException: 배열선언 과정에서 배열 크기를 음수로 지정하는 예외상황
NullPointerException: 참조변수가 null로 초기화 된 상황에서 메소드를 호출하는 예외상황

예제3)

package ex3;

public class Ex2_0623 {
	public static void main(String[] args) {
		int[] arr1=null;
		try {
			arr1 = new int[3];
			arr1[3] =20;
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println(e.getMessage());
			arr1[arr1.length-1]=20;
		}
		System.out.println(arr1[arr1.length-1]);
	}

}

결과3)

Index 3 out of bounds for length 3
20

예제4)

package ex3;

public class Ex2_0623 {
	public static void main(String[] args) {

//		try {
			String str = null;
			int len = str.length();
//		} catch (NullPointerException e) {
//			System.out.println(e.getMessage());
//		}
		// 에러가 발생하면 콘솔창을 잘 읽어보자 예외로 찾아도 되지만
	}
}

결과)

Exception in thread "main" java.lang.NullPointerException: 
Cannot invoke "String.length()" because "str" is null
at ex3.Ex2_0623.main(Ex2_0623.java:8)

ㄴ 트라이 케치문으로 예외를 잡아도 되지만 콘솔창을 잘 읽어보는 습관을 들이자.

6. 예외 클래스의 계층도
- 우리의 관심사는 Error 클래스가 아닌, Exception 클래스에 두어야 한다.
- Error 클래스를 상속하는 예외 클래스는 프로그램 내에서 해결이 불가능한 치명적인 예외상황을 알리는 예외 클래스의 정의에 사용된다.
- VirtualMachineError 클래스가 대표적인데, VME 클래스는 JVM에 문제가 생겨서 더 이상 프로그램의 흐름을 이어갈 수 없는 경우를 알린다.
- Error 클래스는 try-catch로 처리가 불가능한 예외이고 thows 절도 필요없다. JVM에 발생한 문제를 프로그램 내에서 해결할 수 없다. 따라서 이러한 유형의 예외는 JVM에 전달되도록 두어야 한다.

익셉션 위의 상위 클래스도 있다.

- 런타임 익셉션 클래스를 상속하는 하위 클래스들은 예외처리 없이 작성할 수 있다. 선택이 가능하다. 이외의 익셉션은 필수이다.

'ICIA 수업일지' 카테고리의 다른 글

2021.06.25 수업일지  (0) 2021.06.26
2021.06.24 수업일지  (0) 2021.06.26
2021.06.22 수업일지  (0) 2021.06.26
2021.06.21 수업일지  (0) 2021.06.26
2021.06.10 수업일지  (0) 2021.06.20