21.09.08 - 웹 개발 입문 21일차
라이브러리 - Runtime 클래스
Runtime 클래스는 "실행 환경"을 이용할 수 있도록 제공되는 클래스
객체 생성 방식을 제한하여 원하는 형태로만 객체를 만들거나 이용하도록 제약
그래서 객체는 어떻게 만드는가?
객체 생성이 제한된 클래스는 반드시 객체 생성 메소드가 static으로 존재
일반적으로 가장 흔한 이름이 getInstance()이고, 그 외는 get + 클래스이름 으로 구성되는 경우가 많음
package api.lang.etc;
import java.io.IOException;
public class Test03 {
public static void main(String[] args) throws IOException {
// Runtime r = new Runtime();//불가능
Runtime r = Runtime.getRuntime();// 생성이 아닌 생성 요청(만들어주세요~)
// r.exec("notepad.exe");//메모장
// r.exec("mspaint");//그림판
// r.exec("calc");//계산기
r.exec("cmd /c start http://www.naver.com");// 주소를 실행할 수 있는 최적의 방법 탐색
// r.exec("cmd /c shutdown /f /p");//굿바이~
}
}
예외처리 - 에러와 예외 새글
예외(Exception)와 에러(Error)
원치 않는 상황이라는 공통점이 있다.
에러는 컴파일조차 되지 않는 상황(100% 실행이 안됨)
예외는 실행중 오류가 발생한 상황(경우에 따라서 실행이 될 수도 안될 수도 있다)
- 에러 예시
package api.exception;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("쿠폰 개수 입력");
int a = sc.nextInt();
System.out.println("인원 수 입력");
int b = sc.nextInt();
sc.close();
int c = a / b;
System.out.println("한 사람당 줄 수 있는 쿠폰 개수 = " + c);
int d = a % b;
System.out.println("남는 쿠폰 개수 = " + d);
}
}
쿠폰 개수 입력
10
인원 수 입력
0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at api.exception.Test01.main(Test01.java:18)
Q : 프로그램에서 예외가 발생하는 상황과 예외의 이름을 조사해보세요.
A : 이 프로그램에서 발생할 것으로 예상되는 예외는 2가지
예외를 발생하지 않게 만들 수는 없다
예외가 발생한 경우에 예외 메세지 출력 대신 다른 행위를 할 수는 있다.
try ~ catch 구문을 통해 해결!
try는 문제가 발생할 것으로 예상되는 지역을 감시하는 영역(CCTV)
catch는 발생한 문제에 대한 처리를 수행하는 영역(경찰서)
package api.exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test02 {
public static void main(String[] args) {
try {//문제 발생 코드 + 정상 실행 결과 코드
Scanner sc = new Scanner(System.in);
System.out.println("쿠폰 개수 입력");
int a = sc.nextInt();
System.out.println("인원 수 입력");
int b = sc.nextInt();
sc.close();
int c = a / b;
System.out.println("한 사람당 줄 수 있는 쿠폰 개수 = " + c);
int d = a % b;
System.out.println("남는 쿠폰 개수 = "+d);
}
catch(InputMismatchException e){//InputMismatchException 발생 시 실행할 코드 작성
System.err.println("입력 다시해");
}
catch(ArithmeticException e){//ArithmeticException 발생 시 실행할 코드 작성
System.err.println("사람이 0명?");
}
}
}
Test02의 문제점
1. 발생하는 예외가 정말 두 종류 뿐인지 알 수가 없고
2. 두 종류라고 해서 처리블록을 두 개를 만드는게 맞는건지 알 수 없다.
---> 예외를 통합해서 처리할 수도 있나? 가능!
---> 공통된 부모 클래스인 RuntimeException 클래스를 이용하여 하나의 catch 블록으로 통합
package api.exception;
import java.util.Scanner;
public class Test03 {
public static void main(String[] args) {
try {// 문제 발생 코드 + 정상 실행 결과 코드
Scanner sc = new Scanner(System.in);
System.out.println("쿠폰 개수 입력");
int a = sc.nextInt();
System.out.println("인원 수 입력");
int b = sc.nextInt();
sc.close();
int c = a / b;
System.out.println("한 사람당 줄 수 있는 쿠폰 개수 = " + c);
int d = a % b;
System.out.println("남는 쿠폰 개수 = " + d);
}
// catch(RuntimeException e){
catch (Exception e) {// 예외만 처리하고 싶은 경우
// catch(Throwable e) {//에러까지 처리하고 싶은 경우
System.err.println("프로그램에서 오류가 발생했습니다");
}
}
}
Test03의 문제점
Exception을 사용해서 모든 예외를 처리한다는 점은 좋다!
1. 예외를 구분하고 싶을 경우는 어떻게?
2. 예외 메세지가 아예 사라져버렸는데 이를 확인할 방법은 없나?
---> 예외 처리 블록에 존재하는 예외 정보 객체 (e)를 활용할 수 있다.
package api.exception;
import java.util.InputMismatchException;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class Test04 {
public static void main(String[] args) {
try {// 문제 발생 코드 + 정상 실행 결과 코드
Scanner sc = new Scanner(System.in);
System.out.println("쿠폰 개수 입력");
int a = sc.nextInt();
System.out.println("인원 수 입력");
int b = sc.nextInt();
sc.close();
int c = a / b;
System.out.println("한 사람당 줄 수 있는 쿠폰 개수 = " + c);
int d = a % b;
System.out.println("남는 쿠폰 개수 = " + d);
} catch (Exception e) {// 예외만 처리하고 싶은 경우
// System.err.println("프로그램에서 오류가 발생했습니다");
// 에러 메세지(Stack Trace)를 다시 이전처럼 출력하는 명령
// = 개발 단계에서 매우 유용하게 사용되며, 배포 후에는 삭제해야 하는 명령
e.printStackTrace();
// System.err.println(e.getClass());//예외 클래스 정보
// System.err.println(e.getMessage());//내장된 원인 정보(null 일 수 있음)
// JOptionPane.showMessageDialog(null, "오류가 발생했습니다");
}
}
}
Q : 원하는 범위에 예외 처리를 수행하여 "이상한 입력"이 발생한 경우 page가 1로 처리되도록 구현
package api.exception;
import java.util.Scanner;
public class Test05 {
public static void main(String[] args) {
int page;
try {
Scanner sc = new Scanner(System.in);
System.out.print("이동할 페이지 : ");
page = sc.nextInt();
sc.close();
} catch (Exception e) {
page = 1;
}
System.out.println("page = " + page);
}
}
Test05의 문제점
잘못된 값(이상한 입력)에 대한 기준이 개발자와 Java가 서로 다르다
개발자는 정수가 아니거나 또는 0 이하의 정수는 잘못된 값이라고 생각한다
Java는 정수가 아닌 것만 잘못된 값이라고 생각한다
---> 0 이하의 정수가 입력된 경우도 잘못되었다고 "강제"로 알려준다
---> 강제 예외
---> 강제 예외를 발생시키기 위해서는 "예외 객체"를 수동으로 생성해야 한다.
package api.exception;
import java.util.Scanner;
public class Test06 {
public static void main(String[] args) {
int page;
Scanner sc = new Scanner(System.in);
try {
System.out.print("이동할 페이지 : ");
page = sc.nextInt();
if (page <= 0) {
// throw 뒤에 예외객체를 붙여서 catch 블록으로 강제 이동시킬 수 있다.
// = catch 블록에 들어갈 수 있는 형태의 예외 객체를 만들어야 한다.
Exception ex = new Exception();
throw ex;
}
} catch (Exception e) {
page = 1;
}
sc.close();
System.out.println("page = " + page);
}
}
이동할 페이지 : -1
page = 1
Test06의 문제점
Scanner와 같은 통로 형태의 도구는 반드시 close() 작업이 필요하다.
try~catch는 Plan A(try), Plan B(catch) 등 확실하게 실행을 장담할 수 있는 영역이 없다
finally 구문을 추가하여 구문의 마지막에 반드시 실행되는 작업들을 처리할 수 있다.
finally 구문은 선택적으로 사용할 수 있다.
package api.exception;
import java.util.Scanner;
public class Test07 {
public static void main(String[] args) {
int page;
Scanner sc = new Scanner(System.in);
try {
System.out.print("이동할 페이지 : ");
page = sc.nextInt();
if(page <= 0) {
//throw 뒤에 예외객체를 붙여서 catch 블록으로 강제 이동시킬 수 있다.
//= catch 블록에 들어갈 수 있는 형태의 예외 객체를 만들어야 한다.
Exception ex = new Exception();
throw ex;
}
}
catch(Exception e) {
page = 1;
}
finally {
sc.close();
System.out.println("도구 정리 완료");
}
System.out.println("page = " + page);
}
}
JDK 1.8부터는 "통로를 사용하는 try~catch" 구문은 자동 close()를 지원한다
---> try~with 구문
---> 통로 형태의 객체를 사용할 때만 필요한 형태
try(사용할 통로객체 생성) { 감시코드 } catch(예외객체 선언) { 처리코드 }
---> finally 가 없어도 자동 close 수행
package api.exception;
import java.util.Scanner;
public class Test08 {
public static void main(String[] args) {
int page;
try (Scanner sc = new Scanner(System.in);) {
System.out.print("이동할 페이지 : ");
page = sc.nextInt();
if (page <= 0) {
// throw 뒤에 예외객체를 붙여서 catch 블록으로 강제 이동시킬 수 있다.
// = catch 블록에 들어갈 수 있는 형태의 예외 객체를 만들어야 한다.
Exception ex = new Exception();
throw ex;// 강제 에러 발생
}
} catch (Exception e) {
page = 1;
}
System.out.println("page = " + page);
}
}
나누기 기능
발생하는 예외를 처리하기가 매우 애매하다
처리를 하지 않고 미룬다(전가한다)
메소드 마지막에 throws 예외종류를 작성하여 "불완전한" 메소드임을 표시
프로그램 내에서발생하는 예외를 몽땅 모아서 처리할 수 있도록 만들어주는 기술
package api.exception;
public class Calculator {
public int div(int a, int b) throws Exception {
return a / b;
}
}
package api.exception;
public class Test09 {
public static void main(String[] args) {
Calculator c = new Calculator();
try {
int result = c.div(0, 10); // 정상적인 경우
// int result = c.div(10, 0);// 비정상적인 경우
System.out.println("result = " + result);
} catch (Exception e) {
e.printStackTrace();
// System.out.println("사고침.");
}
}
}
예외 처리
package api.exception;
public class Test10 {
public static void main(String[] args) {
System.out.println("안녕하세요");
try {
Thread.sleep(3000L);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("안녕히계세요");
}
}
라이브러리 - 자바의 시간처리
클래스 구현 방법
package api.util.date;
import java.util.Date;
public class Test02 {
public static void main(String[] args) {
// Date 클래스를 이용하여 현재 날짜를 출력
Date a = new Date();
System.out.println(a);
// 비추천된 생성자가 많은 이유
Date b = new Date(2020, 9, 8);
System.out.println(b);
}
}
시간의 형식(Format)을 변경하여 출력
자바는 형식마저도 객체 형태로 제공한다?(java.text.SimpleDateFormat)
형식 객체를 만들고, 형식 객체의 메소드를 이용하여 시간 객체의 설정을 변경한다.
package api.util.date;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test03 {
public static void main(String[] args) {
Date a = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
String time = f.format(a);
System.out.println(time);
}
}
주어진 시간 출력 해보기
package api.util.date;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test04 {
public static void main(String[] args) {
Date d = new Date();
// 업캐스팅 사용
// 2021-09-08 15:36:32
Format f1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(f1.format(d));
// 2021년 9월 8일 수
// Format f2 = new SimpleDateFormat("y년 MMM d일 EEEE");
Format f2 = new SimpleDateFormat("y년 M월 d일 E요일");
System.out.println(f2.format(d));
// 오후 3시 36분 32초
Format f3 = new SimpleDateFormat("a h시 m분 s초");
System.out.println(f3.format(d));
}
}
라이브러리 - Calendar
Calendar 클래스를 이용한 날짜 제어
추상 클래스이며 생성자가 protected이므로 객체 생성이 불가능
클래스 구현 방법
package api.util.calendar;
import java.util.Calendar;
public class Test01 {
public static void main(String[] args) {
// Calendar c = new Calendar();//오류 발생
Calendar c = Calendar.getInstance();// 생성 메소드를 이용해야함
// System.out.println(c);
// 시각 정보 변경
// c.set(무엇을, 얼마로);
// c.set(Calendar.YEAR, 2021);//연도를 2050으로 설정
// c.set(Calendar.MONTH, 9);//월을 10으로 설정(실제보다 1 작게 설정해야함)
// c.set(Calendar.MONTH, Calendar.OCTOBER);
// c.set(Calendar.DATE, 1);//일을 1로 설정
// c.set(Calendar.DAY_OF_MONTH, 1);//일을 1로 설정
// 설정된 시각 정보 추출
System.out.println("YEAR = " + c.get(Calendar.YEAR));// 연도
System.out.println("MONTH = " + c.get(Calendar.MONTH));// 월(0부터 11까지이므로 실제보다 1 작게 나옴)
System.out.println("DATE = " + c.get(Calendar.DATE));// 일
System.out.println("DAY_OF_MONTH = " + c.get(Calendar.DAY_OF_MONTH));// 일
System.out.println("HOUR = " + c.get(Calendar.HOUR));// 시간(12시간방식)
System.out.println("HOUR_OF_DAY = " + c.get(Calendar.HOUR_OF_DAY));// 시간(24시간방식)
System.out.println("MINUTE = " + c.get(Calendar.MINUTE));// 분
System.out.println("SECOND = " + c.get(Calendar.SECOND));// 초
System.out.println("MILLISECOND = " + c.get(Calendar.MILLISECOND));// 밀리초
System.out.println("DAY_OF_WEEK = " + c.get(Calendar.DAY_OF_WEEK));// 요일
System.out.println("AM_PM = " + c.get(Calendar.AM_PM));// 오전(0)/오후(1)
}
}
Calendar 형태의 날짜 정보를 Date로 변환할 수 있는가?
---> 가능하다
package api.util.calendar;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Test02 {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2021, Calendar.DECEMBER, 31);// 2021-12-31
// c에 설정된 날짜를 10일 뒤로 변경(10분 뒤, 10시간 뒤, 10달 뒤, 10년 뒤)
// c.add(Calendar.DATE, 10);//10일 뒤
c.add(Calendar.MONTH, 10);// 10달 뒤
Date d = c.getTime();
Format f = new SimpleDateFormat("yyyy-MM-dd E");
System.out.println(f.format(d));
}
}
Q. 디데이 계산기 구현
package api.util.calendar;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Test03 {
public static void main(String[] args) {
int count = 100;
Calendar c = Calendar.getInstance();
c.set(2021, Calendar.DECEMBER, 25);// 2021-12-25
c.add(Calendar.DATE, -count + 1);// 100일 전
Date d = c.getTime();
Format f = new SimpleDateFormat("yyyy-MM-dd E");
System.out.println(f.format(d));
}
}
100일 전 날짜는 : 2021-09-17 금