오늘 수업 내용
* 클래스와 인스턴스 활용하는 여러 예제를 다룬다.
* 메소드 오버로딩(메소드 중복 정의)에 대해 배운다.
- 메소드 오버라이딩(메소드 재정의)과 명칭이 비슷해서 헷갈릴 수 있다. 메소드 오버라이딩은 자바15(2020.0824) 에서 다룬다.
* 만년달력 예제를 다룬다.
* 주민번호 유효성 검사 예제를 다룬다. (예전에는 실무적으로 사용했지만 현재는 잘 사용하지 않는다. 연습용 예제)
메소드 오버로딩(Method Overloading, 메소드 중복 정의)
메소드가 처리하는 기능은 같고
- 메소드 괄호 속에 오는 인수(인자, 매개변수, 파라미터)의 갯수가 다르거나
- 메소드 괄호 속에 오는 인수의 자료형(Data Type)이 다른 경우
메소드의 이름을 동일한 이름으로 부여하여 메소드를 정의할 수 있도록 문법적으로 허용하게 되는데 이를 메소드 오버로딩(Method Overloading)이라고 한다.
* 메소드 오버로딩을 사용할 때 메소드의 반환형은 같아야하며, 매개변수는 같으나 반환형은 다르다는 조건은 메소드 오버로딩에 성립되지 않는다.
ex) ①void write(int n) / ②void write(String str) → write("김소소") 를 호출하면 ②메소드를 호출한 것
ex) ①int print() / ②void print() → print() 메소드를 호출했을 때 둘 중 어떤 메소드를 호출한 건지 전혀 구분할 수 없으므로 메소드 오버로딩이 성립되지 않는다.
※ 메소드 오버로딩 : 메소드 중복 정의 (같은 이름의 메소드를 정의한다.)
※ 메소드 오버라이딩 : 메소드 재정의 (상속받은 메소드의 정의부를 새로 정의한다. 자바15 포스팅 참조)
예제 코드
/*=================================================
■■■ 메소드 중복정의(Method Overloading) ■■■
=================================================*/
public class Test106
{
public static void main(String[] args)
{
drawLine();
//--==>> ====================
drawLine('+');
//--==>> ++++++++++++++++++++
drawLine('>');
//--==>> >>>>>>>>>>>>>>>>>>>>
drawLine('/', 50);
//--==>> //////////////////////////////////////////////////
drawLine('+', 30);
//--==>> ++++++++++++++++++++++++++++++
}
// 선을 그리는 메소드 정의
public static void drawLine()
{
System.out.println("====================");
}
// 선의 형태를 바꾸어 그리는 메소드 정의
public static void drawLine(char c)
{
for (int i=0; i<20; i++)
{
System.out.print(c);
}
System.out.println();
}
// 선의 형태와 길이를 바꾸어 그리는 메소드 정의
public static void drawLine(char c, int n)
{
for (int i=0; i<n; i++)
{
System.out.print(c);
}
System.out.println();
}
}
메소드 오버로딩(Method Overloading) 이 가능한 형태와 불가능한 형태
/*===================================================
■■■ 메소드 중복정의(Method Overloading) ■■■
- Method Overloading 이 가능한 형태와 불가능한 형태
===================================================*/
public class Test107
{
public static void main(String[] args)
{
print('A');
double result = print(10.0);
print(10.0);
}
public static void print() {}
public static void print(int i) {}
// print('A') : 매개변수 char 함수 없어도 매개변수 int 함수 불러서 컴파일 할 수 있음
//public static void print(int j) {} //--(x)
public static void print(char c) {} //-- 자동 형 변환 규칙 check 하면서 써야함
public static void print(int i, int j) {}
public static void print(double d) {} //-- 자동 형 변환 규칙 check 하면서 써야함
//public static double print(double d) {return 3.14;} //--(x)
//public static void print(double d) {return 3.14;} //-- 정의 불가
//public static void print(double e) {} //--(x)
}
클래스와 인스턴스 활용 예제 1
학생별로 국어점수, 영어점수, 수학점수를 입력받아 총점, 평균을 계산하는 프로그램을 구현한다.
단, 클래스의 개념을 활용하여 작성할 수 있도록 한다.
또한, 이 과정에서 배열을 적극적으로 활용할 수 있도록 한다.
○프로그램을 구성하는 클래스
1. Record 클래스 → 속성만 존재하는 클래스로 설계할 것
2. Sungjuk 클래스 → 인원 수를 입력받아, 입력받은 인원 수 만큼 이름, 국어점수, 영어점수, 수학점수를 입력받고 총점과 평균을 산출하는 클래스로 설계할 것
· 속성 : 인원수, Record 형태의 배열
· 기능 : 인원수 입력, 상세 데이터 입력, 총점 및 평균 연산, 결과 출력
3. Test104 클래스 → main() 메소드가 존재하는 외부 클래스로 설계할 것
/*===============================
■■■ 클래스와 인스턴스 ■■■
- 클래스와 인스턴스 활용
===============================*/
// Record.java / Sungjuk.java / Test104.java 세트~!
// 1. Record 클래스
public class Record
{
// 학생 1명을 표현할 수 있는 속성들로 구성
String name; //-- 이름
int[] score = new int[3]; //-- 각 과목의 점수 → int kor, eng, mat;
int tot; //-- 총점
double avg; //-- 평균
int rank; //-- 등수(석차)
}
/*===============================
■■■ 클래스와 인스턴스 ■■■
- 클래스와 인스턴스 활용
===============================*/
// Record.java / Sungjuk.java / Test104.java 세트~!
// 2. Sungjuk 클래스
import java.util.Scanner;
public class Sungjuk
{
// 주요 속성 구성(주요 변수 선언)
int inwon; //-- 인원 수
Record[] rec; //-- Record 배열(학생 한 명 당 Record 배열 방 한 개 활용)
// Record를 기반으로 생성된 객체만 담아낼 수 있는 배열
// 주요 메소드 구성(기능 구성 → 메소드 정의)
// ① 인원 수 입력
public void set()
{
Scanner sc = new Scanner(System.in);
do
{
System.out.print("인원 수 입력(1~100) : ");
inwon = sc.nextInt();
}
while (inwon<1 || inwon>100);
// check~!!!
// Record 클래스를 기반으로 생성된 객체(인스턴스)를 담을 수 있는
// 배열방을 inwon 만큼 생성한 것이지
// Record 클래스의 인스턴스를 생성한 것은 아니다.
rec = new Record[inwon];
}
// 주요 메소드 구성(기능 구성 → 메소드 정의)
// ② 상세 데이터 입력 (이름, 국어점수, 영어점수, 수학점수 입력) + 총점 평균 산출
public void input()
{
Scanner sc = new Scanner(System.in);
String[] title = {"국어 점수 : ", "영어 점수 : ", "수학 점수 : "};
// 인원 수 만큼 반복 → 인원 수에 기반하여 만들어진 배열의 길이만큼 반복
for (int i=0; i<inwon; i++) // for (int i=0; i<rec.length; i++)
{
// check~!!! (가장 핵심!!!★★★)
// Record 클래스 기반의 인스턴스 생성
//Record ob = new Record();
//rec[i] = ob;
rec[i] = new Record();
//rec[i].name = "홍길동";
System.out.printf("%d번째 학생의 이름 입력 : ", (i+1));
rec[i].name = sc.next();
for (int j=0; j<title.length; j++)
{
// 안내 메세지 출력
System.out.print(title[j]);
// 사용자가 입력한 데이터를 스코어(score) 배열에 담아내기
rec[i].score[j] = sc.nextInt(); // score[0] → 국어 점수
// score[1] → 영어 점수
// score[2] → 수학 점수
// 국어, 영어, 수학 점수 데이터 입력받는 동안
// 총점 누적하기
rec[i].tot += rec[i].score[j];
}
// 평균 산출하기
rec[i].avg = rec[i].tot / 3.0;
}
}// end input()
// 주요 메소드 구성(기능 구성 → 메소드 정의)
// ③ 결과 출력
public void print()
{
// 석차 산출 메소드 호출~!!! (구문 추가)
ranking();
System.out.println(); // 개행
// 학생 한 명 당 반복 출력 구문 구성
for (int i=0; i<inwon; i++)
{
// 이름 출력
System.out.printf("%5s", rec[i].name);
// 성적(국어, 영어, 수학) 반복 출력
for (int j=0; j<3; j++)
{
System.out.printf("%4d", rec[i].score[j]);
}
// 총점, 평균 출력
System.out.printf("%5d", rec[i].tot);
System.out.printf("%6.2f", rec[i].avg);
// 석차 출력구문 추가~!!! (구문 추가)
System.out.printf("%5d", rec[i].rank);
System.out.println();
}
}// end print()
// ④ 석차 산출 메소드 추가
// - Record 배열의 rank 속성 초기화를 수행하는 기능 → 반환 자료형 void
// - 클래스 내부에서 활용할 메소드로 정의
// 즉, 외부에 노출할 메소드가 아닌 형태로 정의 → 접근제어 지시자 private
// → 외부에서 접근(호출) 불가
private void ranking()
{
// 모든 학생들의 등수(석차, rank)를 1로 초기화
for (int i=0; i<inwon; i++)
rec[i].rank = 1;
// 등수 산출
for (int i=0; i<inwon-1; i++) // 비교 기준 0 1 2 3
{
for (int j=i+1; j<inwon; j++) // 비교 대상 1234 234 34 4
{
// 기준의 평균이 대상의 평균보다 크다면...
if (rec[i].avg > rec[j].avg)
{
// 대상의 rank 를 1 만큼 증가
rec[j].rank++;
}
else
{
// 기준의 rank 를 1만큼 증가
rec[i].rank++;
}
}
}
}// end ranking()
}// end class Sungjuk
/*===============================
■■■ 클래스와 인스턴스 ■■■
- 클래스와 인스턴스 활용
===============================*/
// Record.java / Sungjuk.java / Test104.java 세트~!
// 실행 예)
// 인원 수 입력(1~100) : 102
// 인원 수 입력(1~100) : -10
// 인원 수 입력(1~100) : 3
// 1번째 학생의 이름 입력 : 윤홍준
// 국어 점수 : 90
// 영어 점수 : 80
// 수학 점수 : 70
// 2번째 학생의 이름 입력 : 김승범
// 국어 점수 : 82
// 영어 점수 : 7
// 수학 점수 : 62
// 3번째 학생의 이름 입력 : 이예슬
// 국어 점수 : 98
// 영어 점수 : 88
// 수학 점수 : 78
// 윤홍준 90 80 70 240 xx.xx 2
// 김승범 82 72 62 xxx xx.xx 3
// 이예슬 98 88 78 xxx xx.xx 1
// 계속하려면 아무 키나 누르세요...
public class Test104
{
public static void main(String[] args)
{
Sungjuk ob = new Sungjuk();
ob.set();
ob.input();
ob.print();
}
}
클래스와 인스턴스 활용 예제 2
1 ~ 3 사이의 난수를 발생시켜서 가위, 바위, 보 게임 프로그램을 구현한다.
단, 클래스의 개념을 활용하여 처리할 수 있도록 한다.
또한, 배열을 활용하여 처리할 수 있도록 한다.
최종적으로 RpsGame 클래스를 완성할 수 있도록 한다.
/*===============================
■■■ 클래스와 인스턴스 ■■■
- 클래스와 인스턴스 활용
===============================*/
// ※ 기준 데이터 → 1:가위, 2:바위, 3:보
// 실행 예)
// 1:가위, 2:바위, 3:보 중 입력(1~3) : 4
// 1:가위, 2:바위, 3:보 중 입력(1~3) : -1
// 1:가위, 2:바위, 3:보 중 입력(1~3) : 2
// - 유저 : 바위
// - 컴퓨터 : 보
// >> 승부 최종 결과 : 컴퓨터가 이겼습니다~!!!
// 계속하려면 아무 키나 누르세요...
import java.util.Scanner;
import java.util.Random;
class RpsGame
{
// ○ 주요 속성 구성(변수 선언)
private int user;
private int com;
//private String resultStr;
// ○ 주요 기능 구성(메소드 정의)
// - 사용자의 선택 내용을 입력받는 기능의 메소드
public void input()
{
runCom();
Scanner sc = new Scanner(System.in);
do
{
System.out.print("1:가위, 2:바위, 3:보 중 입력(1~3) : ");
user = sc.nextInt();
}
while (1>user || user>3);
}
private void runCom()
{
Random rd = new Random();
com = rd.nextInt(3) + 1; //-- 『+1』 : 0 1 2 → 1 2 3
}
// ○ 주요 기능 구성(메소드 정의)
// - 중간 결과 출력(서로의 선택 내용 확인)
public void middleCalc()
{
String[] str = {"가위", "바위", "보"};
System.out.println();
System.out.println(" - 유저 : " + str[user-1]);
System.out.println(" - 컴퓨터 : " + str[com-1]);
//-- 『-1』 : str[1] str[2] str[3] → str[0] str[1] str[2]
}
// ○ 주요 기능 구성(메소드 정의)
// - 승부에 대한 연산
public String resultCalc()
{
String result = "무승부 상황입니다~!!!";
// (유저=="가위" && 컴=="보") || (유저=="바위" && 컴=="가위") || (유저=="보" && 컴=="바위")
if ((user==1 && com==3) || (user==2 && com==1) || (user==3 && com==2)) // 당신이 승리한 상황
{
result = "당신이 승리했습니다~!!!";
}
// (유저=="가위" && 컴=="바위") || (유저=="바위" && 컴=="보") || (유저=="보" && 컴=="가위")
else if ((user==1 && com==2) || (user==2 && com==3) || (user==3 && com==1)) // 컴퓨터가 승리한 상황
{
result = "컴퓨터가 승리했습니다~!!!";
}
return result;
}
// ○ 주요 기능 구성(메소드 정의)
// - 최종 결과 출력
public void print(String str)
{
System.out.printf("\n>> 승부 최종 결과 : %s\n", str);
}
}
// main() 메소드를 포함하고 있는 외부의 다른 클래스
public class Test105
{
public static void main(String[] args)
{
RpsGame ob = new RpsGame();
ob.input();
ob.middleCalc();
String result = ob.resultCalc();
ob.print(result);
}
}
// 실행 결과
/*
1:가위, 2:바위, 3:보 중 입력(1~3) : 1
- 유저 : 가위
- 컴퓨터 : 바위
>> 승부 최종 결과 : 컴퓨터가 승리했습니다~!!!
계속하려면 아무 키나 누르십시오 . . .
1:가위, 2:바위, 3:보 중 입력(1~3) : 2
- 유저 : 바위
- 컴퓨터 : 바위
>> 승부 최종 결과 : 무승부 상황입니다~!!!
계속하려면 아무 키나 누르십시오 . . .
1:가위, 2:바위, 3:보 중 입력(1~3) : 3
- 유저 : 보
- 컴퓨터 : 가위
>> 승부 최종 결과 : 컴퓨터가 승리했습니다~!!!
계속하려면 아무 키나 누르십시오 . . .
*/
만년 달력 예제
/*======================
■■■ 만년달력 ■■■
======================*/
// 실행 예)
// 『연도』를 입력하세요 : 2021
// 『월』을 입력하세요 : 1
/*
[ 2021년 1월 ]
일 월 화 수 목 금 토
============================
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
============================
계속하려면 아무 키나 누르세요...
*/
import java.util.Scanner;
public class Test108
{
int totDay;
int y, m;
int[] months = {0,31,28,31,30,31,30,31,31,30,31,30,31};
String[] weekday = {"일","월","화","수","목","금","토"};
// 날짜 입력
void input()
{
Scanner sc = new Scanner(System.in);
System.out.print("『연도』를 입력하세요 : ");
y = sc.nextInt();
System.out.print("『월』을 입력하세요 : ");
m = sc.nextInt();
}
// m월 1일의 요일 계산
int firstDay()
{
totDay = (y-1)*365 + (y-1)/4 - (y-1)/100 + (y-1)/400;
if (y%400==0 || (y%4==0 && y%100!=0)) //윤년의 2월달은 29
months[2] = 29;
else //평년의 2월달은 28
months[2] = 28;
for (int i=1; i<m; i++)
totDay += months[i];
totDay++; // m월 1일
return totDay%7;
}
// 달력 출력
void print(int weekday)
{
// 출력(달력 그리기)
System.out.printf("\n\t[ %d년 %d월 ]\n", y, m);
System.out.println(" 일 월 화 수 목 금 토");
System.out.println("============================");
// 특정 요일부터 1일이 출발할 수 있도록 공백 발생(지정)
for (int i=0; i<weekday; i++)
{
System.out.print(" ");
}
// 테스트(확인)
//System.out.printf("%4d", 1);
// 해당 월(입력한 월)의 날짜만 출력될 수 있도록 반복문 구성
for (int i=1; i<=months[m]; i++)
{
System.out.printf("%4d", i); // 1 2 3 4 5 6 ... 31
weekday++; // 7 8 9 10 ...
if (weekday%7==0) // 일요일에 해당하는날짜일 경우
System.out.println(); // 개행
}
// 달의 마지막 날짜가 출력 형식을 모두 채웠을 경우
// 이미 일요일 개행이 이루어졌기 때문에
// 이 경우에는 추가 개행을 하지 않도록 처리
if(weekday%7!=0)
System.out.println();
System.out.println("============================");
}
public static void main(String[] args)
{
Test108 ob = new Test108();
ob.input();
int weekday = ob.firstDay();
//System.out.println(weekday); // 테스트
ob.print(weekday);
}
}
주민번호 유효성 검사 예제
과거에는 실무에 사용했지만 현재는 사용되지 않는다. 하지만 제어문을 다루는 연습으로는 좋은 로직이다.
예제를 푸는데 도움이 되는 메소드
* 배열.length : 배열의 길이(배열 방의 갯수)를 반환
* 문자열.length() : 문자열의 길이 반환
* 문자열.substring(i, j) : 문자열 index i번째에서 j-1번째 까지 반환(j는 포함되지 않는다.)
※ 주민등록번호 검증 공식
① 마지막 자리를 제외한 12개의 각 자리 수를 규칙에 맞게 곱한다.
123456-1234567 (주민번호)
234567 892345 (각 자리에 곱해질 수)
② 규칙에 맞게 곱셈 연산을 수행한 결과를 모두 더한다.
ex) 7 5 0 6 1 5 - 1 8 6 2 1 3 3
2 3 4 5 6 7 8 9 2 3 4 5
--------------------------------
→ (7*2) + (5*3) + (0*4) + (6*5) + (1*6) + (5*7) + (1*8) + (8*9) + (6*2) + (2*3) + (1*4) + (3*5)
→ 14 + 15 + 0 + 30 + 6 + 35 + 8 + 72 + 12 + 6 + 4 + 15 = 217
③ 더해진 결과값을 11로 나누어 『나머지』를 취한다.
217 % 11 = 8 (나머지)
④ 11에서 나머지(8)을 뺀 결과값을 구한다.
11 - 8 = 3 (결과값)
※ 만약 ③의 처리 과정에서 나머지가 0인 경우이거나 1인 경우에는
11-0 = 11 또는 11-1 = 10
이를 다시 10으로 나눈 나머지를 결과값으로 한다. (1 또는 0 이 결과값)
⑤ 결과값이 주민번호의 마지막 숫자와 일치하는지의 여부를 확인한다.
일치 → 유효한 주민번호
불일치 → 잘못된 주민번호
/*======================================
■■■ 주민등록번호 유효성 검사 ■■■
======================================*/
// 실행 예)
// 주민번호 입력(xxxxxx-xxxxxxx) : 123456-12345678 → 입력 갯수 초과
// >> 입력 오류~!!!
// 계속하려면 아무 키나 누르세요...
// 주민번호 입력(xxxxxx-xxxxxxx) : 123456-123456→ 입력 갯수 미달
// >> 입력 오류~!!!
// 계속하려면 아무 키나 누르세요...
// 주민번호 입력(xxxxxx-xxxxxxx) : 750615-1252085 → 유효한 주민번호
// >> 정확한 주민번호~!!!
// 계속하려면 아무 키나 누르세요...
// 주민번호 입력(xxxxxx-xxxxxxx) : 750615-1252084 → 유효하지 않은 주민번호
// >> 잘못된 주민번호~!!!
// 계속하려면 아무 키나 누르세요...
//import java.util.Scanner;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Test109
{
public static void main(String[] args) throws IOException
{
/*
// 문자열.length() 테스트
strTemp = "동해물과 백두산이";
System.out.println(strTemp.length());
//--==>> 9
strTemp = "study-hard";
System.out.println(strTemp.length());
//--==>> 10
// 문자열.substring() 테스트
strTemp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println(strTemp.substring(3, 5)); // 3 ~ 4
//--==>> "DE"
System.out.println(strTemp.substring(13, 17)); // 13 ~ 16
//--==>> "NOPQ"
//System.out.println(strTemp.substring(13, 57)); // 13 ~ 56
//--==>> 에러 발생 → StringIndexOutOfBoundsException
strTemp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println(strTemp.substring(15)); // 15 ~
//--==>> "PQRSTUVWXYZ"
*/
// BufferedReader 인스턴스 생성
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 입력 받는 주민번호(문자열 형태)
String str;
// 주민번호의 각 자릿수에 곱하게 될 수 → 배열 형태로 구성
// 7 5 0 6 1 5 - 1 8 6 2 1 3 3
// * * * * * * * * * * * * *
int[] chk = {2, 3, 4, 5, 6, 7, 0, 8, 9, 2, 3, 4, 5};
// 곱셈 연산 후 누적합
int tot = 0;
System.out.print("주민번호 입력(xxxxxx-xxxxxxx) : ");
str = br.readLine();
if (str.length() != 14)
{
System.out.println(">> 입력 오류~!!!");
return; //-- 메소드종료 → main() 메소드 종료 → 프로그램 종료
}
// ex) 750615-1252085
for (int i=0; i<13; i++)
{
if (i==6)
continue;
//chk[i] * Integer.parseInt(주민번호 특정 자릿수 추출);
tot += chk[i] * Integer.parseInt(str.substring(i, (i+1)));
//chk[0] * Integer.parseInt("750615-1252085".substring(0, 1));
//chk[0] * Integer.parseInt("7");
//2 * 7
//chk[1] * Integer.parseInt("750615-1252085".substring(1, 2));
//chk[1] * Integer.parseInt("5");
//3 * 5
// :
//chk[6] * Integer.parseInt("750615-1252085".substring(6, 7));
//0 * Integer.parseInt("-");
}
// ③ ④ 관련 연산 수행
int su = 11 - tot%11;
// 테스트(확인)
//System.out.println(su);
// 최종 결과 출력 이전에... 추가 연산 필요~!!!
// su 에 대한 연산 결과가 두 자리로 나올 경우
// 주민번호 마지막 자리의 숫자와 비교할 수 없는 상황
su = su % 10; // su %= 10;
if (su == Integer.parseInt(str.substring(13)))
System.out.println(">> 정확한 주민번호~!!!");
else
System.out.println(">> 잘못된 주민번호~!!!");
}
}
'자바 풀스택 과정 수업 정리 > 자바' 카테고리의 다른 글
자바 15-1 (2020.08.24) : 상속, super (0) | 2020.08.29 |
---|---|
자바 14 (2020.08.21) : 정렬 알고리즘(선택, 버블, 삽입, 향상된 버블) (0) | 2020.08.28 |
자바 12-2 (2020.08.19) : 클래스 변수, 클래스 메소드, 인스턴스 변수, 인스턴스 메소드 (0) | 2020.08.24 |
자바 12-1 (2020.08.19) : 접근제어 지시자, 정보은닉, 캡슐화 (0) | 2020.08.23 |
자바 11-2 (2020.08.18) : 난수(Random 클래스), 배열의 복사 (0) | 2020.08.23 |
최근댓글