CalendarMain02
생성package kr.s03.date;
import java.util.Calendar;
import java.util.Scanner;
public class CalendarMain02 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("희망 연도와 월을 입력하세요! (예: 연도 > 2021, 월 > 7)");
System.out.print("연도 > ");
int year = input.nextInt();
System.out.print("월 > ");
int month = input.nextInt();
input.close();
System.out.println("[ " + year + "년 " + month + "월 ]");
System.out.println("========");
System.out.println("일 월 화 수 목 금 토");
// 현재 날짜와 시간을 구함; new로 객체 생성 불가
Calendar cal = Calendar.getInstance();
// 희망 연도, 월, 일 세팅; 월의 범위는 0~11이기 때문에 입력 월-1, 일은 달력이 1일부터 시작하기 때문에 1일로 세팅
cal.set(year, month-1, 1);
// 1일의 요일을 구하기; 요일의 범위는 1=일요일, 7=토요일
int week = cal.get(Calendar.DAY_OF_WEEK);
// 월의 마지막 날짜 구하기
int lastOfDate = cal.getActualMaximum(Calendar.DATE);
// 첫 날짜를 표시하기 전 공백 처리
for(int i=1;i<week;i++) {
System.out.printf("%3s", " "); // 3칸 잡고 공백 넣음
}
// 1일부터 마지막 날짜까지 표시
for(int i=1;i<=lastOfDate;i++) {
System.out.printf("%3d", i); // 3칸 잡고 날짜 넣음
if(week%7==0) System.out.println(); // 토요일이면 줄바꿈
week++;
}
System.out.println("\n========");
}
}
java.util
패키지에 포함되어 있음
split()
메서드와 달리, 복수의 구분자 지정 가능true
전달시 구분자를 토큰에 포함split()
메서드와 달리) 배열을 반환하지 않으므로 for문이 아니라 메서드를 이용하여 토큰에 접근hasMoreTokens()
true
, 그렇지 않으면 false
를 반환하는 메서드nextToken()
kr.s04.string
생성 후 새 클래스 StringTokenizerMain01
생성package kr.s04.string;
import java.util.StringTokenizer;
public class StringTokenizerMain01 {
public static void main(String[] args) {
String source = "100,200,300,400";
StringTokenizer st = new StringTokenizer(source, ",");
while(st.hasMoreTokens()) { // hasMoreTokens() 메서드로 구분자를 통해 만들어진 문자열이 있는지 검증
System.out.println(st.nextToken()); // nextToken() 메서드로 구분자를 통해 만들어진 문자열을 하나씩 반환
}
}
}
StringTokenizerMain02
생성package kr.s04.string;
import java.util.StringTokenizer;
public class StringTokenizerMain02 {
public static void main(String[] args) {
String source = "2021-11-10 11:21:50";
StringTokenizer st = new StringTokenizer(source, "-: "); // 복수의 구분자 지정 가능
while(st.hasMoreTokens()) { // 구분자를 통해 만들어진 문자열이 있는지 검증
System.out.println(st.nextToken()); // 구분자를 통해 만들어진 문자열을 하나씩 반환
}
}
}
.class
확장자를 갖기 때문에 컴파일 전 코드를 확인해야 인터페이스인지 클래스인지 구분 가능ch06-object2
프로젝트에 새 패키지 kr.s11.inter
생성하고 새 클래스 InterMain01
생성package kr.s11.inter;
interface A1 {
// 상수; 인터페이스는 생성자가 없으므로 객체 생성이 불가능하고, 상수는 각자 호출시 메모리에 올라감
public static final int W = 10; // 원형
int X = 20; // public static final 생략해도 원형대로 선언됨
static int Y = 30; // public final 생략해도 원형대로 선언됨
final int Z = 40; // public static 생략해도 원형대로 선언됨
}
public class InterMain01 {
public static void main(String[] args) {
// 인터페이스는 객체 생성 불가
// A1 ap = new A1();
// static 상수이므로 인터페이스명.상수명 형식으로 호출함
System.out.println("W = " + A1.W);
System.out.println("X = " + A1.X);
System.out.println("Y = " + A1.Y);
System.out.println("Z = " + A1.Z);
}
}
InterMain02
생성package kr.s11.inter;
interface A2 {
// 추상 메서드; 인터페이스는 객체 생성이 불가하므로 일반 클래스에서 구현하여 사용
public abstract void getA(); // 원형
void getB(); // public abstract 생략해도 원형대로 선언됨
}
// 인터페이스를 클래스에 구현
class B2 implements A2 {
// 인터페이스의 추상 메서드를 구현; 구현되지 않은 추상 메서드가 있을 경우 오류 발생
@Override public void getA() {
System.out.println("getA 메서드");
}
@Override public void getB() {
System.out.println("getB 메서드");
}
}
public class InterMain02 {
public static void main(String[] args) {
B2 bp = new B2();
bp.getA();
bp.getB();
}
}
InterMain03
생성package kr.s11.inter;
interface Inter1 {
// 추상 메서드
public abstract int getA();
}
interface Inter2 {
// 추상 메서드
public abstract int getB();
}
// Inter1과 Inter2가 Inter3에 상속; 인터페이스끼리는 상속이 가능하며, 다중 상속도 인정됨
interface Inter3 extends Inter1, Inter2 {
// 추상 메서드
public abstract int getData();
}
interface Inter4 {
// 추상 메서드
public abstract String getStr();
}
// 클래스에 Inter3과 Inter4를 구현; 한 클래스에 여러 인터페이스를 동시에 구현 가능
class InterSub implements Inter3, Inter4 {
// Inter3의 추상 메서드 구현
@Override public int getA() {
return 10;
}
@Override public int getB() {
return 20;
}
@Override public int getData() {
return 30;
}
// Inter4의 추상 메서드 구현
@Override public String getStr() {
return "서울";
}
}
public class InterMain03 {
public static void main(String[] args) {
InterSub is = new InterSub();
System.out.println(is.getA());
System.out.println(is.getB());
System.out.println(is.getData());
System.out.println(is.getStr());
}
}
InterMain04
생성package kr.s11.inter;
interface I {
// 추상 메서드
public abstract void play();
}
// 인터페이스 I를 클래스 B에 구현
class B implements I {
@Override public void play() {
System.out.println("피아노를 연주합니다.");
}
public void study() {
System.out.println("외국어를 공부합니다.");
}
}
public class InterMain04 {
public static void main(String[] args) {
B bp = new B();
bp.play();
bp.study();
I i = bp; // 클래스 자료형에서 인터페이스 자료형으로 자동 형변환
i.play();
// i.study(); // 호출 범위를 벗어나므로 호출 불가
B bp2 = (B)i; // 인터페이스 자료형에서 클래스 자료형으로 강제 형변환
bp2.play();
bp2.study();
}
}
InterMain05
생성package kr.s11.inter;
interface Inter {
// 추상 메서드
public abstract void play();
}
class A implements Inter {
@Override public void play() {
System.out.println("피아노를 연주합니다.");
}
}
class C implements Inter {
@Override public void play() {
System.out.println("첼로를 연주합니다.");
}
}
class Admin {
public void autoPlay(Inter i) {
// i를 통해 객체에 접근해서 메서드를 호출함; 공통 자료형을 사용하지 못하면 메서드를 클래스 자료형마다 별도로 만들어야 하며, Object 자료형의 경우 play() 메서드 호출 불가
i.play();
}
}
public class InterMain05 {
public static void main(String[] args) {
Admin ad = new Admin();
ad.autoPlay(new A());
ad.autoPlay(new C());
}
}
java.lang
패키지에 포함된 기본 클래스java.lang
패키지에 포함된 기본 클래스java.lang
패키지에 포함된 기본 클래스ch08-exception
생성하고 새 패키지 kr.s01.exception
생성 후 새 클래스 ExceptionMain01
생성package kr.s01.exception;
public class ExceptionMain01 {
public static void main(String[] args) {
int[] array = {10,20,30};
// 인위적으로 예외를 발생시키기 위해 없는 인덱스 3을 호출
for(int i=0;i<=array.length;i++) {
System.out.println("array[" + i + "] : " + array[i]);
} // for문 종료
System.out.println("프로그램 정상 종료"); // 예외 발생으로 프로그램 비정상 종료되어 출력되지 않음
}
}
ExceptionMain02
생성package kr.s01.exception;
public class ExceptionMain02 {
public static void main(String[] args) {
// 예외 처리; 예외가 발생해도 정상 종료될 수 있도록 프로그램적으로 처리
int[] array = {10, 20, 30};
// 인위적으로 예외 발생
for(int i=0;i<=array.length;i++) {
// 예외 처리; 예외는 없는 인덱스를 호출하는 순간 발생
try { // 예외가 발생할 가능성이 있는 코드를 명시
System.out.println("array[" + i + "] : " + array[i]);
}
catch(ArrayIndexOutOfBoundsException e) { // 예외 발생시 catch 블럭으로 이동하여 예외가 발생한 이유를 출력하거나 대체 코드를 실행; catch()에는 예외 발생시 생성되는 예외 객체의 자료형을 지정해야 함
System.out.println("없는 인덱스 " + i + "을/를 호출함");
}
} // for문 종료
System.out.println("프로그램 정상 종료"); // 예외 처리를 했기 때문에 예외가 발생해도 출력됨
}
}
ExceptionMain03
생성package kr.s01.exception;
public class ExceptionMain03 {
public static void main(String[] args) {
int var = 50;
// 예외가 발생하면 예외 객체가 생성되고, 예외 객체가 전달된 catch 블럭으로 이동해서 수행문을 실행
try {
int data = Integer.parseInt(args[0]);
System.out.println(var/data);
}
// 다중 catch문 사용; Exception과 하위 예외 클래스를 동시에 명시할 경우, 하위 예외 클래스를 먼저 명시하고 마지막에 Exception을 명시해야 동작상의 문제가 발생하지 않음; 부모 클래스는 자식 클래스의 예외 객체를 모두 흡수할 수 있고, catch()문은 순차적으로 확인하기 때문
catch(NumberFormatException e) { // 데이터가 "100"이면 100으로 parsing하지만 "100?"이면 예외 발생
System.out.println("숫자가 아닙니다.");
}
catch(ArrayIndexOutOfBoundsException e) { // 프로그램 실행시 인자를 전달하지 않은 경우, 배열이 만들어지지 않아 args[0] 호출시 예외 발생
System.out.println("입력한 데이터가 없습니다.");
}
catch(ArithmeticException e) { // var/0 연산시 예외 발생
System.out.println("0으로 나눌 수 없습니다.");
}
catch(Exception e) { // 예외가 발생할 것으로 예상되지만 정확한 클래스명을 모를 경우, 부모 클래스 자료형으로 자동 형변환하여 예외 처리 가능
System.out.println("예외가 발생했습니다.");
}
System.out.println("프로그램 정상 종료");
}
}
close()
하는 등, 자원 정리가 필요한 경우에 사용ExceptionMain04
생성package kr.s01.exception;
public class ExceptionMain04 {
public static void main(String[] args) {
// try~catch~finally
System.out.println("예외가 발생하지 않는 경우");
try {
System.out.println("1");
System.out.println("2");
}
catch(Exception e) {
System.out.println("3");
}
finally {
System.out.println("4");
}
System.out.println("========");
System.out.println("예외가 발생하는 경우");
try {
System.out.println("1");
System.out.println(10/0); // 인위적으로 ArithmeticException 발생
System.out.println("2");
}
catch(Exception e) {
System.out.println("3");
}
finally {
System.out.println("4");
}
System.out.println("========");
}
}
throws
예약어 다음에 발생할 가능성이 있는 예외 클래스명을 명시하고, 메서드 내에 tryReadLine()
메서드는 try~catch문을 작성하지 않으면 컴파일 에러ExceptionMain05
생성package kr.s01.exception;
import java.io.IOException; // BufferedReader의 예외를 처리하기 위해 필요
import java.io.BufferedReader; // 범용적으로 Scanner보다 많이 사용됨
import java.io.InputStreamReader; // BufferedReader를 사용하기 위해 필요
public class ExceptionMain05 {
// 메서드에 throws 예약어를 사용하여 발생할 가능성이 있는 예외 클래스들을 명시하면, 메서드 내에 try~catch 블럭을 생략하고, 예외가 발생하면 예외를 보관하고 메서드를 호출한 곳에서 try~catch 블럭을 만들고 그 곳으로 예외를 양도
public void printData() throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("단 입력 > ");
int dan = Integer.parseInt(br.readLine()); // readLine() 메서드는 \n, \r, \r\n이 제거된 한 줄의 데이터를 문자열로 반환하므로 문자열 parsing 필요; readLine() 메서드 사용시 IOException이 발생할 수 있고, IOException은 일반적 Exception이라 throws 혹은 try~catch하지 않으면 컴파일 오류 발생
System.out.println(dan + "단");
System.out.println("========");
for(int i=1;i<=9;i++) {
System.out.println(dan + " * " + i + " = " + dan*i);
}
}
public static void main(String[] args) {
ExceptionMain05 ex = new ExceptionMain05();
// ex.printData(); // throws 예약어 사용한 메서드 호출시 의무적으로 try~catch 블럭 작성해야 함
try {
ex.printData();
}
catch(NumberFormatException e) {
System.out.println("잘못 입력하셨습니다. 숫자만 입력하세요.");
}
catch(IOException e) { // IOException은 입력 대기 중인데 프로그램을 강제 중단하거나, 시스템 환경이 불안정한 경우 등에 발생 가능하며 돌발적으로 발생하기 때문에 예외 처리를 의무화하는 것; 이 예제에서는 프로그램 강제 중단시 parseInt()의 인자가 없기 때문에 NumberFormatException도 함께 발생
System.out.println("입출력 예외가 발생했습니다.");
}
}
}
ch07-langnUtil
의 패키지 kr.s02.mathtest
에 새 클래스 RandomMain02
생성package kr.s02.mathtest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RandomMain02 {
public static void main(String[] args) {
/*
* [실습] 가위바위보 게임
* 컴퓨터가 난수를 발생시켜 0=가위, 1=바위, 2=보를 낸다.
* 메뉴 > 1. 게임하기, 2. 종료
* [출력 예시]
* 가위바위보 입력 > 0. 가위, 1. 바위, 2. 보
* 경우 1) 무승부! (컴퓨터 : 가위, 당신 : 가위)
* 경우 2) 컴퓨터 승리! (컴퓨터 : 가위, 당신 : 보)
* 경우 3) 당신 승리! (컴퓨터 : 가위, 당신 : 바위)
*/
RandomMain02 game = new RandomMain02();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
all: while(true) {
System.out.println("메뉴 > 1. 게임하기, 2. 종료");
System.out.print("메뉴 > ");
int menu=0;
try {
menu=Integer.parseInt(br.readLine());
}
catch(Exception e) {
System.out.println("예외 발생");
}
switch(menu) {
case 1:
System.out.println("가위바위보 입력 > 0. 가위, 1. 바위, 2. 보");
System.out.print("가위바위보 입력 > ");
int player=-1;
try {
player=Integer.parseInt(br.readLine());
}
catch(Exception e) {
System.out.println("예외 발생");
}
game.judge(player);
break;
case 2:
System.out.println("게임 종료"); break all;
default:
System.out.println("메뉴를 잘못 입력하셨습니다."); break;
}
}
}
public void judge(int player) {
java.util.Random random = new java.util.Random();
int ai=random.nextInt(3);
String[] card={"가위", "바위", "보"};
String[] winlose={"무승부!", "승리!"};
String[] winner={"", "컴퓨터 ", "당신 "};
int result=1;
int who=1;
if(player==ai) {
result=0;
who=0;
}
else if(player==0){
if(ai==2) {
who=2;
}
}
else if(player==1) {
if(ai==0) {
who=2;
}
}
else if(player==2) {
if(ai==1) {
who=2;
}
}
else {
System.out.println("가위바위보를 잘못 입력하셨습니다.");
return;
}
System.out.printf("%s%s (컴퓨터: %s, 당신: %s)\n", winner[who], winlose[result], card[ai], card[player]);
}
}