본문 바로가기
백엔드/자바

자바 - 16

by study_yeon 2023. 5. 19.

2023.05.18

 

● 예외처리

1. 컴파일오류
- 컴파일러에 의해 발생
- 빨간줄 등
- 오타 등 소스코드에 문제가 생기면 발생

2. 실행오류(런타임오류)
- 실행하는 알고리즘이 잘못되어 발생
- 실행을 해야 알 수 있음


-> 자바에서는 오류를 예외라고 한다.


1) 실행 예외(기본)
ex) 0으로 나누는 경우 
- 클래스 : DivideExceptionApp 

-> 실행예외 발생

 

* IntegerInt .parseInt (): 컨버전메소드 

- 문자열을 정수로 변환함

-> 키보드로 입력받은 것은 숫자를 입력해도 문자열로 들어오기 때문에 정수형으로 변경이 필요


* 예외 해결방안
※ 내 생각 : 범위지정
- if활용

if (0 < num2) {
    return;
    } else {
    System.out.println("숫자를 다시 입력해주세요.");
}

-> 해도 예외 발생(근본적인 해결이 안됨)


● 예외 해결방안
수업

클래스 : DivideExceptionApp2
1) 프로그래머가 해결하기 : if, while 등 구체적 조건 명시
2) 예외처리하기

 trycatch : 실행할 실제 구문(try) + 예외 가정문(catch)을 통해 에러를 확인(해결)함 

- 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성함

- Exception ex : 모든 예외가 처리됨 [ Exception(모든 예외의 조상), ex(변수)  ]

- 자바가 캐치하는 오류를 개발자가 캐치하도록 변경

- 배열을 사용하는 경우에 trycatch를 사용할 것

- 선언부는 try에 안들어감: {}안에 선언부가 들어가면 지역변수가 되기 때문에
-> 지역변수로 사용되야 하는 경우는 try안에 작성

-> 현재 코드에서는 안으로 들어가는게 좋음 

▷ try catch finally : 실행후 오류 방지

public class DivideExceptionApp2 {

	public static void main(String[] args) {
		int num1 = 1000;
		int num2 = 0;
			
		try {
			System.out.printf("%d / %d = %d ", num1, num2, (num1 / num2));
		} catch (Exception ex ) {
			System.out.println("예외가 발생했습니다.");
		} finally {  // 필수는 아님
			System.out.println("나는 무조건 마지막에 실행됩니다.");
		}
	}
	
}

- catch에서 놓치는경우가 발생할 수 있으니 finally까지 활용(필수는 아님)

divide 메소드로 변경

public class DivideExceptionApp2 {

	public static void main(String[] args) {
		int num1 = 1000;
		int num2 = 0;
			
		try {  // divide() 메소드 실행 
			divide(num1, num2); 
		} catch (Exception ex ) {
			System.out.println("예외가 발생했습니다.");
		} finally {  // 필수는 아님
			System.out.println("나는 무조건 마지막에 실행됩니다.");
		}
	}
	
	// 2. divide 메소드
	private static void divide(int num1, int num2) {  // 한 번만 만들면 되는 부분(static)
		System.out.printf("%d / %d = %d ", num1, num2, (num1 / num2));
	}
}

1. divide() 메소드를 만들어 밖으로 빼기

System.out.printf("%d / %d = %d ", num1, num2, (num1 / num2));

- 상단의 소스코드를 divide() 메소드로 변경
- static안에 있어서 메소드도 static이 되어야 함

static 컴파일 오류

2. try문안에 메소드 실행 


● 시큐어 프로그래밍법 
1. 변수는 일단 상수(값이 안변한다는 전제)
2. 함수(메소드)의 접근범위는 최소화

* args는 프로그램 외부에서 프로그램을 실행할때 넘겨주는 인수값의 배열
- 이렇게 넘어오는 인수값은 기본적으로 문자열임 따라서 Intger.parseInt()처리(정수로 변환)가 필요
 예) DivideExceptionApp3 1000 0

 

* args : 명령프롬프트로부터 값 받아오기 
- RunAs > Run Configurations > Arguments에서 설정

- 구분기호는 공백임 


* (참고) Show Command Line의 내용을 복사하여 명령프롬프트로 실행할때 활용 
-> 엔터키가 안들어간 한 줄로 작성해야됨

노란 밑줄부분처럼 한줄로 붙여넣기


▷ throws : 선택적 예외를 발생(우리가 선택한 예외) - 메서드에 예외 선언하기

- 사용법 : 함수시그니처 + throws + 미리 대비할 예외타입 + 함수본체{}

- 클래스 : DivideExceptionApp3

package myexception;

public class DivideExceptionApp3 {

	public static void main(String[] args) {
		try {
			int num1 = Integer.parseInt(args[0]); // Run Configurations에서 값 설정
			int num2 = Integer.parseInt(args[1]);
			divide(num1, num2); 
		} catch(ArithmeticException ae) { // 에러가 나는 구역을 정해주기 throws
			System.out.println("두번째 숫자는 0이 아닌 수를 입력해주세요");
		} catch(Exception ex) {
			System.out.println("예외가 발생했습니다. : " + ex);
		} 
		
	}
	
	private static void divide(int num1, int num2) throws ArithmeticException{
		System.out.println("나눗셈 결과 : " + (num1 / num2));
	}

}

- ArithmeticException ae : 산술계산 예외

- throws 구문을 사용하여 예외가 발생할지도 모르니 상위처리부분(함수호출)에서 대비해주세요라고 미리 공지하는 것
- 예외가 발생했을때 예외를 호출한 쪽에서 처리하도록 던져준다.(예외 던지기)

-> ArithmeticException에서 예외를 처리하도록 함

- num1(100) / num2(0)일 경우 [두번째 숫자는 0이 아닌 수를 입력해주세요] 출력

 

* (참고) try catch catch ...를 사용할때 작은 에러처리부터 작성

- 큰 범위의 에러처리를 먼저 작성하면 에러 처리가 완료되기 때문에 다음 에러처리(세부)를 작성할 필요가 없어짐


▷ throw : 강제로 오류를 발생시킴 - 예외 발생시키는 키워드

사용법 : try 부분에 throw new 발생시킬예외();
-> catch에서 활용
- 클래스 : InvalidInputExceptionApp

package myexception;

public class InvalidInputExceptionApp {

	public static void main(String[] args) {
		try {
		// 자바시험 점수를 입력하려고 합니다
		int javascore = Integer.parseInt(args[0]); // 명령프롬프트로부터 값 받아오기
		
		if (javascore < 0) {
			// System.out.println("0이상의 수를 입력해주세요.");
			throw new IllegalArgumentException();  // 강제로 오류 발생(잘못된 인수가 넘어왔다라는 뜻)
		}
		System.out.println("입력한 자바점수 : " + javascore);
		} catch(IllegalArgumentException e) {
			System.out.println("0이상의 점수를 입력해주세요.");
		}
		
	}

}

 

- 음수는 0점 처리(범위를 벗어나면 예외처리)
* 예외처리 하지않고 종료하는 느낌?
- args배열 활용 시 명령프롬프트로부터 값 받아오지 않으면 오류 

●  throw와 throws의 차이
- throw는 만약 어떤 연산을 하다가 예상치 못한 일이 발생했을 때 Exception을 발생시켜 예외가 처리될 수 있도록 함. 
Application이 예외를 적절히 처리하지 못하면 프로그램이 죽거나 오동작하게 됩니다.
IllegalArgumentException라는 다른 예외 발생

- throws는 메소드를 정의할 때 사용하며, 이 메소드에서 발생할 수 있는 Exception을 명시적으로 정의할 때 사용 
이 메소드를 사용할 때 예외가 발생할 수 있음을 알려줌 (catch에서 활용)


★ 미니프로젝트 : 학생관리프로그램


※ 조건
- 클래스 2개 이상
- 학생 입력하는 기능 / 출력 기능
- 찾기(검색) / 수정 / 삭제 기능 추가
- 메뉴는 종료를 눌러야 빠져나옴 (루프 활용)

- 학생은 배열이용[main에 생성(DAO로 따로 분리 가능)]

 

※ 소스코드 작성 전 계획하기

1. package membermini;
2. class Student에 들어갈 내용
- 멤버변수 : 

 id(숫자, 학생번호)
 name(문자열)
 age(숫자)
 kor(숫자, 국어성적)
 eng(숫자, 영어성적)
 math(숫자, 수학성적)

- 메소드 

 생성자(기본생성자)
 속성함수(get, set)
 기능함수(toString(), equals(), sum(), avg())
 (참고)equals : 데이터형이 같은 데이터인가(instanceof)


3. class StudentApp : 성적관리 실행클래스
- 메소드 : main()


- 실행클래스(StudentApp)의 화면구조설계 - main()안에 작성될 내용

# 메뉴화면 (sysout 활용)
>>>> 중앙자바클래스 학생관리 프로그램<<<<  // 제목
 1. 입력  2. 출력  3. 종료                
실행할 메뉴를 입력해주세요. :   // 메뉴번호 입력 받음 Scanner활용

# 1. 입력화면 (sysout , Scanner활용)
학생정보를 입력해주세요 :
학생번호 :  ______
학생이름 :  ______ 
국어 :  ______
영어 :  ______
수학 :  ______

# 2. 출력화면
[1.] 학생정보
이름 : 황진이
나이 :  18세
국어 : 100점
영어 : 100점
수학 : 100점
------------
총점 : 300점
평균 : 100점

# 3. 종료화면 
(공백)
----프로그램을 종료합니다. ----

 

* CI/CD(지속적 통합/지속적 제공 또는 배포)
애플리케이션의 통합 및 테스트 단계에서부터 제공 및 배포에 이르는 애플리케이션의 라이프사이클 전체에 걸쳐 지속적인 자동화와 지속적인 모니터링을 제공. 


● 미니프로젝트 앞단부터 만들기


1. 메뉴화면 
2. 스캐너
3. 초이스한 메뉴에 따라 연결되는 실행함수(입력 - view)   // 입력된 것들이 모인것이 - data(model)
4. 실행함수에서 각 기능(입력, 출력, 종료) 실행

 

0. 유틸메소드 만들기 (main()밖의 영역에 작성)

static void p(String msg) {
		System.out.print(msg);
	}
	static void pl(String msg) {
		p(msg + "\n");
	}

 

1. 메뉴 화면 프린트

- 프린트할 내용 적기(루프 적용)

boolean isRun = true;  // 센티널변수: 메뉴 4번을 실행하면 루프에서 빠짐기능을 만들기 위함
while(isRun) { 
	pl(">>>> 중앙자바클래스 학생관리 프로그램 <<<<");
	pl("--------------------------------");
	pl("  1. 입력  2. 출력  3. 초기화  4. 종료 ");
	pl("실행할 메뉴를 입력해주세요. : ");
	int choice = sc.nextInt(); // 숫자 입력을 받기 위한 변수
}

* 센티널변수
while에서 빠져나오는 기능을 자연스럽게하기 위하여 사용(강제종료는 프로그래머가 구현하면 안됨)
->  빠져나오기 : 변수의 값을 반대로 뒤집음(iSRun = false)

실행화면

2. 스캐너 : 메뉴선택을 위한 키보드 입력 준비

Scanner sc = new Scanner(System.in);

3. 초이스한 메뉴에 따라 연결되는 실행함수

- if(또는 switch)문으로 메뉴 고르기 기능 만들기

-> if는 범위를 비교하는데 주로 사용 

// 1. else if 활용

if(choice == 1) { 
	pl("1번메뉴를 선택하셨습니다.");
} else if (choice == 2) {
	pl("2번메뉴를 선택하셨습니다.");
} else if (choice == 3) {
	pl("모든 자료가 삭제됩니다.");	
} else if (choice == 4){
	pl("");
	pl("프로그램을 종료합니다.");
	break; // if문을 빠져나오는 기능
} else {
	pl("메뉴를 다시 선택해주세요.");
}

->  switch 는 값으로 딱 떨어지는 값 비교에 주로 사용

// 2. switch 활용 
switch (choice) {
case 1 :
	// 학생정보입력
	pl("1번메뉴를 선택하셨습니다.");
	break;
case 2 :
	// 학생정보출력
	pl("2번메뉴를 선택하셨습니다.");
	break;
case 3 : 
	// 초기화
	pl("모든 자료가 삭제되었습니다.");
	break;
case 4 :
	// 종료
	pl("");
	pl("프로그램을 종료합니다.");
	isRun = false; // while은 빠져나오는 기능 
	break; // switch문을 빠지는 조건(while은 빠져나오지 못함)
default :  // 없어도 됨 
	pl("메뉴를 다시 선택해주세요.");
	break;
}


4. 실행함수에서 각 기능(입력, 출력, 종료) 실행
4-1. 학생정보입력
- scanner을 이용하여 학생정보 입력

- Student 객체 생성

case 1 :
	// 학생정보입력
    pl("1번메뉴를 선택하셨습니다.");
    // Student 객체 생성
    Student st = new Student();
    // scanner을 이용하여 학생정보 입력 - 멤버변수로 들어감(set 활용) 
    p("학생 번호 : ");
    st.setId(sc.nextInt());
    p("학생 이름 : ");
    st.setName(sc.next());
    p("국어 성적 : ");
    st.setKor(sc.nextInt());
    p("영어 성적 : ");
    st.setEng(sc.nextInt());
    p("수학 성적 : ");
    st.setMath(sc.nextInt());

    // list에 student 추가
    list.add(st);
    break;

 

실행화면

※ arraylist 배열  - 전체에서 사용하니까 위에 작성
-> 한계가 없다, 인덱스번호로 얻어옴
import java.util.ArrayList;  하기

public static void main(String[] args) {
	ArrayList<Student> list = new ArrayList<>();
	pl("list의 크기 : " + list.size()); // 확인용
}

* ArrayList는 List 인터페이스를 상속받은 클래스로 크기가 가변적으로 변하는 선형리스트입니다.
일반적인 배열과 같은 순차리스트이며 인덱스로 내부의 객체를 관리한다는점등이 유사하지만 한번 생성되면 크기가 변하지 않는 배열과는 달리 ArrayList는 객체들이 추가되어 저장 용량을 초과하면 자동으로 부족한 크기만큼 저장 용량이 늘어남.

제네릭 타입: <Student>
* 자바에는 자료를 보관하는 여러가지 방법이 있다.
그 중에 데이터형식에 자료형식을 표시하는 방법중에 배열과 유사한 기능을 가지는 ArrayList<데이터명> 변수명과 같이 사용형식을 리스트라고 한다
 ArrayList<데이터형>의 뜻은  ArrayList리스트에 저장되는 값의 타입이 데이터형식의 값이다.

4-2. 학생정보출력
* 학생정보가 없으면 출력이 안됨(레코드개수가 있을때와 없을때 구분하기) 

case 2 :
	// 학생정보출력
	pl("학생 크기 : " + list.size());
	// 리스트에 자료가 없는 경우 -> 자료가 없습니다.
	if (list.size() == 0) {
        pl("출력할 학생정보가 없습니다.");

	} else { // 리스트에 자료가 있는 경우 -> 반복문이 필요
		for(int i = 0; i < list.size(); i++) { 
		// 리스트로부터 i번째 요소를 가져와라 
			pl(list.get(i).toString());
		}
	}
	break;

타입에러
실행화면

4-3. 초기화
* 리스트에 있는 데이터 삭제하기 
- 메뉴 손보기(3. 초기화  추가)

case 3 : 
	// 초기화
	list.clear(); // 현재 리스트의 모든 데이터 초기화
	pl("모든 자료가 삭제되었습니다.");
	break;

 

- clear() 메소드 활용
list.clear();

- 로컬변수가 사라지기 전에 case1에 list.add(st); 추가

실행화면

4-4. 종료 (+ 메뉴에 없는번호를 선택하였을 경우(default))

case 4 :
    // 종료
    pl("");
    pl("프로그램을 종료합니다.");
    isRun = false; // while은 빠져나오는 기능 
    break; // switch문을 빠지는 조건(while은 빠져나오지 못함)
    
default : 
	// 메뉴에 없는 번호를 선택한 경우
	pl("메뉴를 다시 선택해주세요.");
	break;
}

 

실행화면


** 객체의 특성 
작업영역  : 
1. 스택(stack)
- LIFO(last in first out)
ex) 물류창고
2. 큐()
- FIFO(first in first out)
ex) 에스컬레이터


Student.zip
0.00MB

 

'백엔드 > 자바' 카테고리의 다른 글

자바 - 18 (데이터베이스 연결)  (0) 2023.05.22
자바 - 17  (0) 2023.05.21
자바 - 15  (0) 2023.05.18
자바 - 14  (0) 2023.05.17
자바 - 13  (0) 2023.05.16