package upcasting;
class A01{
public void test() {
System.out.println("aaaa");
}
}
class B01 extends A01{
public void test() {
System.out.println("bbbb");
}
}
class C01 extends A01{
public void test() {
System.out.println("cccc");
}
}
public class Ex01 {
public static void main(String[] args) {
A01 a;
// 자식 클래스를 부모 클래스 자료형 형태로 저장 = 업캐스팅
a = new B01(); a.test(); // bbbb
a = new C01(); a.test(); // cccc
/*
B01 b;
C01 c;
b = new B01(); // b 객체화
c = new C01(); // c 객체화
b.test(); // bbbb 출력
c.test(); // cccc 출력
*/
}
}
업캐스팅 예시 ( 위와 같이 업캐스팅한 경우 부모 자료형 변수 a 에 자식 클래스를 객체화 시키면 메소드가 오버라이딩되기 때문에 자식 클래스의 메소드만 출력된다 )
package upcasting;
class Parents{
public void famillyName() {
System.out.println("이");
}
public void name() {
famillyName();
System.out.println("순신");
}
}
class Daughter extends Parents{
public void name() {
famillyName();
System.out.println("국주");
}
}
class Son extends Parents{
public void name() {
famillyName();
System.out.println("기광");
}
}
public class Ex02 {
public static void main(String[] args) {
/*
Parents par = new Parents();
par.name();
Daughter d = new Daughter();
d.name();
Son s = new Son();
s.name();
*/
// 1번 아빠이름, 2번 딸이름, 3번 아들이름
// 번호를 선택함에 따라 해당 이름이 나오게 세팅
Parents par;
// Daughter d;
// Son s;
// Daugter, Son 클래스의 부모클래스가 모두 Parents로 같으니
// 번호 선택 시 부모 클래스 변수에 자식 클래스를 객체화하여 사용 ( 메소드 오버라이딩됨 )
int num = 3;
if(num == 1) {
par = new Parents();
par.name();
}else if(num == 2) {
par = new Daughter();
par.name();
}else if(num == 3) {
par = new Son();
par.name();
}
}
}
업캐스팅 사용 예시
다운캐스팅 ( downcasting )
package upcasting;
class Test{}
public class Ex03 {
public static void main(String[] args) {
// 업캐스팅 ( int, String 자료형을 부모 형태의 자료형에 저장 )
Object num = 100;
Object name = "홍길동";
Object t = new Test();
System.out.println(num.getClass()); // class java.lang.Integer
System.out.println(name.getClass()); // class java.lang.String
// 컴파일 오류 발생
// 오버라이딩이 진행되어 num 변수의 자료형이 Object 로 변경되었기 때문
// int a = 100 + num;
// 다운캐스팅 ( Object 로 업캐스팅된 num 을 int 형으로 명시하여 다운캐스팅 )
int a = 100 + (int)num;
System.out.println(a);
}
}
업캐스팅된 자료를 기존의 자료처럼 사용하려면 본인의 형태로 되돌리는 다운캐스팅 과정이 필요하다
package overriding;
class Ferrari{
private int ye;
public Ferrari(int ye) {
this.ye = ye;
}
public int getYe() {
return ye;
}
public void speed() {
System.out.println(ye + "년식 페라리 속도 : 300km 달립니다");
}
public void onCar() {
System.out.println("자동차 시동을 켭니다!!!");
}
}
class NewFerrari extends Ferrari{
public NewFerrari(int ye) {
super(ye);
}
public void autoSystem() {
// 페라리를 상속받아 새로운 메소드를 추가
System.out.println("자동 운전모드를 실행합니다!!!");
}
public void speed() {
// 부모의 speed() 메소드를 오버라이딩 ( overriding )
// 오버라이딩 할 때는 접근제한자, 반환 자료형, 메소드명을 동일하게 해야한다
// 또한 오버라이딩을 하는 자식 클래스의 접근제한자는 부모클래스보다 크거나 같아야한다
System.out.println("500km 까지 달릴 수 있습니다!");
}
}
public class Ex01 {
public static void main(String[] args) {
NewFerrari f = new NewFerrari(2024);
f.onCar();
f.speed();
f.autoSystem();
}
}
오버라이딩 ( Overriding ) 예시
1. 오버라이딩을 할 때는 자식 클래스의 접근제한자는 부모 클래스의 접근 제한자보다 크거나 같아야 한다.
2. 오버라이딩 시 부모가 가지고 있는 메소드와 ( 접근 제한자, 반환 자료형, 메소드 이름 ) 이 동일해야 한다
package overriding;
import java.util.ArrayList;
class Test02 extends ArrayList<String>{
// ArrayList 를 상속
// get() 메소드 오버라이딩
public String get(int i) {
System.out.println( super.get(i) );
return super.get(i);
}
}
public class Ex02 {
public static void main(String[] args) {
Test02 t = new Test02();
t.add("111");
t.add("222");
t.add("333");
// 기존의 get() 메소드는 String 형태로 값을 반환만 해줌, 출력 X
// get() 메소드를 오버라이딩하여 해당 값을 바로 출력하게끔 변경
t.get(2);
// 3 출력
}
}
ArrayList 오버라이딩 예시
( 오버라이딩 코드에서 프린팅 값과 return 값에 super. 를 사용하지 않으면 자기 자신의 메소드가 재실행 되므로 무한으로 코드가 재실행되어 StackOverflowError 가 발생하기 때문에 super. 를 사용하여 부모 클래스의 값을 호출하여 사용한다.
final
package overriding;
final class Test03{
public void test() {
System.out.println("test03의 test 기능");
}
}
class TestClass03 { // extends Test03 불가
// 에러 발생 final 클래스는 상속을 받을 수 없음
public void test() {
System.out.println("Testclass03의 test 기능");
}
}
public class Ex03 {
public static void main(String[] args) {
TestClass03 t = new TestClass03();
Test03 t3 = new Test03();
// final 이 붙은 클래스는 상속을 받아 사용할 수 없으므로
// 객체화하여 사용해야 한다
t3.test();
}
}
final 을 붙이는 경우 상속, 오버라이딩 등을 변경할 수 없는 상태가 된다
위에서 만약 TestClass03 클래스가 Test03 클래스를 상속 받으려고 extends Test03 을 입력하면 컴파일 오류가 출력된다
package overriding;
class Test04{
// 메소드의 접근제한자가 protected
protected void test() {
System.out.println("부모 실행");
}
}
class TestClass04 extends Test04{
// test() 메소드 오버라이딩된 상태
// 부모 클래스의 test() 메소드가 protected 이며 오버라이딩
// 접근제한자로 설정한 것이 public 이므로 부모의 접근제한자보다
// 크기 때문에 오버라이딩이 가능하다
// 만약 부모 클래스의 접근제한자보다 작다면 오버라이딩이 불가하다 ( 컴파일 오류 )
public void test() {
System.out.println("자식 실행");
}
}
public class Ex04 {
public static void main(String[] args) {
}
}
오버라이딩 시 접근제한자는 오버라이딩 하려는 부모 클래스의 메소드보다 무조건 커야한다
package overriding;
class TestDTO{
String name;
int age;
// toString() 메소드를 오버라이딩
// 저장된 공간이 출력되는 toString() 메소드는 자체로
// 사용할 일이 많이 없기 때문에 오버라이딩하여 사용하는 경우가 많다
@Override
public String toString() {
return "[name : " + name + ", age = " + age + "]";
}
}
class Test06{
TestDTO t;
// 생성자
public Test06() { t = new TestDTO(); }
// 메소드
public void setDTO() {
t.name = "홍길동";
t.age = 200;
}
public void print() {
System.out.println(t.name);
System.out.println(t.age);
System.out.println("------------------");
System.out.println(t.toString());
// 오버라이딩 전 : overriding.TestDTO@43a25848
// 오버라이딩 후 : [name : 홍길동, age = 200]
System.out.println(t);
// 오버라이딩 전 : overriding.TestDTO@43a25848
// 오버라이딩 후 : [name : 홍길동, age = 200]
}
}
public class Ex06 {
public static void main(String[] args) {
Test06 t = new Test06();
t.setDTO();
t.print();
// 오버라이딩 전 : overriding.TestDTO@43a25848
// 오버라이딩 후 : [name : 홍길동, age = 200]
}
}
toString() 메소드를 오버라이딩
toString 메소드는 모든 자료에 다 내재되어 있으며 해당 메소드를 사용하면 저장된 메모리 공간이 출력된다, 하지만 이 기능을 사용할 일이 없으므로 오버라이딩하여 많이 사용하며 해당 메소드 오버라이딩은 DTO 클래스에서 진행하는 경우가 많다
package exception;
import java.util.Scanner;
public class Ex01 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int x, y, result = 0;
System.out.print("수 입력 : ");
x = input.nextInt();
System.out.print("수 입력 : ");
y = input.nextInt();
try {
result = x / y ;
// try 코드에서 문제가 발생하면 catch 로 넘어간다
// try 에서 문제가 없다면 catch 를 진행하지 않고 다음 코드로 넘어간다
}catch(ArithmeticException e) {
// 0 으로는 나눌 수 없는 예외를 처리
System.out.println("문제 발생");
System.out.println("0으로 나눌 수 없음");
}
System.out.println("결과 : " + result);
}
}
발생하는 예외와 일치하는 예외로 처리해줘야 한다
( 예외 클래스들의 부모 클래스인 Exception 으로 통합하여 예외처리도 가능하다 )
package exception;
import java.util.Scanner;
public class Ex02 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num;
while(true) {
System.out.print("수 입력 : ");
num = input.nextInt();
try {
System.out.println("결과 : " + (100/num));
} catch(Exception e) {
// Exception 은 예외들의 부모 클래스
System.out.println(e);
System.err.println("에러 : " + e); // 빨간 글씨로 출력
// java.lang.ArithmeticException: / by zero
// 에러 : java.lang.ArithmeticException: / by zero
}
}
}
}
예외 처리 예시
package exception;
import java.util.ArrayList;
public class Ex03 {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<>();
arr.add("111"); // index : 0
arr.add("222"); // index : 1
arr.add("333"); // index : 2
for(int i=0; i<=arr.size(); i++) {
// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
try {
System.out.println(arr.get(i));
} catch(IndexOutOfBoundsException e) {
System.out.println(e);
// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
}
}
System.out.println("다음 문장 실행!!!");
}
}
예외 처리 예시
package exception;
import java.util.ArrayList;
public class Ex03 {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<>();
arr.add("111"); // index : 0
arr.add("222"); // index : 1
arr.add("333"); // index : 2
for(int i=0; i<=arr.size(); i++) {
// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
try {
int n1 = 10, n2 = 0;
System.out.println(n1/n2);
System.out.println(arr.get(i));
} catch(IndexOutOfBoundsException e) {
System.out.println(e);
// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
} catch(ArithmeticException e) {
System.out.println(e);
// java.lang.ArithmeticException: / by zero
}
}
System.out.println("다음 문장 실행!!!");
}
}
예외 처리는 오버라이드 ( override ) 를 사용하여 각자 발생하는 예외를 매개변수로 갖는 메소드로 향하게 설정이 가능하다
package exception;
import java.util.Scanner;
public class Ex05 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x;
System.out.println("수 입력");
x = sc.nextInt();
try {
int result = 10 / x;
System.out.println("결과 : " + result);
return;
}catch (Exception e) {
// 예외가 발생된 내용을 자세하게 출력
e.printStackTrace();
}finally {
// finally 는 try 가 실행되든지 catch 가 실행되든지
// 무조건 실행되는 코드
// return 으로 해당 코드를 종료해도 finally 는 무조건적으로 실행된다
System.out.println("finally 실행");
sc.close();
// finally 를 사용하여 Scanner 스트림을 무조건 종료시키는 코드 실행
}
System.out.println("다음 문장들 실행!!!");
}
}
e.printStackTrace(); - 예외의 자세한 내용을 출력
finally - 예외가 발생되던지 발생되지 않던지 해당 코드는 진행이 된다
( finally 는 try/catch 에만 사용할 수 있는 것이 아니므로 꼭 실행해야 하는 코드가 있다면 finally 처리를 해주면 된다 )
예외 전가
package exception;
public class Ex07 {
public static void main(String[] args) throws InterruptedException {
// 예외 전가를 사용하여 예외 처리
// 예외처리를 해줘야 하는 Thread.sleep(); 메소드
// 예외처리 해주지 않으면 컴파일 오류가 발생한다
Thread.sleep(1000);
}
}
예외 전가
package exception;
class Test06{
public void test1() throws InterruptedException {
System.out.println("1111");
// test2() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
test2();
}
public void test2() throws InterruptedException {
System.out.println("2222");
// 첫 예외 발생 > throws 로 예외 전가
Thread.sleep(1000);
}
}
public class Ex06 {
public static void main(String[] args) throws InterruptedException {
Test06 t = new Test06();
// t.test1() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
t.test1();
// 1111
// 2222
}
}
예외 전가의 문제점
( 메소드를 호출하여 사용할때 해당 메소드에서 예외를 전가했다면 호출한 클래스에서도 예외를 처리해줘야 한다 )
( 만약 최초 예외가 발생된 곳에서 try / catch 로 개별로 예외를 처리해줬다면 해당 메소드를 호출해도 호출한 클래스에서는 예외가 발생하지 않는다 )
강제 예외
package exception;
import java.util.Scanner;
public class Ex08 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int age = 0;
System.out.print("나이 입력 : ");
try {
age = sc.nextInt();
if(age < 0) {
throw new Exception("음수는 입력불가!!!");
}
} catch (Exception e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
System.out.println("당신의 나이는 : " + age);
}
}
package inheritance;
import java.util.ArrayList;
class TestClass03 extends ArrayList<String>{
// ArrayList 를 상속받은 TestClass03
// 부모 클래스의 get 메소드를 오버라이딩
@Override
public String get(int index) {
System.out.println("데이터를 가져오는 기능");
return super.get(index);
}
// 부모 클래스의 add 메소드를 오버라이딩
@Override
public boolean add(String e) {
System.out.println("데이터를 추가했습니다.");
return super.add(e);
}
}
public class MainClass03 {
public static void main(String[] args) {
TestClass03 tc = new TestClass03();
tc.add("aaa");
// 데이터를 추가했습니다.
System.out.println(tc.get(0));
// 데이터를 가져오는 기능
// aaa
}
}
상속과 오버라이딩
상속 - extends 를 사용
오버라이딩 - Alt + Shift + S 후 Override/Implement Methods... 클릭
Override / Implement Methods....
상속을 사용한 경우와 사용하지 않은 경우의 코드 차이점 ( 상속을 사용한 경우가 더 간결한 코드로 작성이 가능하다 )
상속을 사용하는 이유
- 이미 만들어져 있는 클래스를 재사용하기 때문에 효율적이고 중복된 코드가 줄어든다
- 유지보수가 쉽다
- 확장성이 용이하다
- 재사용이 가능하다
- 코드가 간결해진다
super
package inheritance;
class Test06 {
public void test() {
System.out.println("부모 test 메소드");
}
}
class TestClass06 extends Test06 {
public void test() {
System.out.println("자식 test 메소드");
}
public void display() {
// test 메소드를 실행했을때 자기 자신에게 test 메소드가 없고
// 부모 클래스에 test 메소드가 있다면 부모의 test 메소드를 실행한다
test(); // 자식 test 메소드 출력
this.test(); // 자식 test 메소드 출력
super.test(); // 부모 test 메소드 출력
// super : 부모 클래스를 의미
// this : 자기 자신 클래스를 의미
}
}
public class MainClass06 {
public static void main(String[] args) {
TestClass06 tc = new TestClass06();
tc.display();
}
}
super 와 this
package inheritance;
class Test07{
public Test07() {
System.out.println("부모 생성자 실행");
}
}
class TestClass07 extends Test07{
public TestClass07() {
System.out.println("자식 생성자 실행");
}
}
public class MainClass07 {
public static void main(String[] args) {
TestClass07 tc = new TestClass07();
// 부모 생성자 실행
// 자식 생성자 실행
// 자식을 객체화 했을때 상속받은 부모의 생성자부터 실행되며
// 부모의 생성자가 실행된 이후 자식의 생성자가 실행된다
}
}
상속 받을 경우 생성자의 실행 순서 ( 부모 -> 자식 )
package inheritance;
class Test08{
public Test08(String s) {
System.out.println(s + "부모 생성자 실행!!!");
}
}
class TestClass08 extends Test08{
public TestClass08() {
// 부모 클래스의 생성자가 문자열을 필요로하기 때문에
// super(); 안에 문자열을 적어 부모 클래스 생성자를
// 호출할때 해당 값을 전달한다
// 이때, 사용하는 super(); 는 무조건 생성자의 맨 첫 줄에
// 적어야 한다!!!!
super("값 전달\n");
System.out.println("자식 생성자 실행!!!");
}
}
public class MainClass08 {
public static void main(String[] args) {
TestClass08 tc = new TestClass08();
// 값 전달
// 부모 생성자 실행!!!
// 자식 생성자 실행!!!
}
}
부모 클래스의 생성자가 매개변수를 필요로 하는 경우
package inheritance;
class Test09{
public Test09() {
System.out.println("부모 기본 생성자");
}
public Test09(String s) {
System.out.println(s + " : 부모 생성자");
}
}
class TestClass09 extends Test09{
public TestClass09() {
System.out.println("자식 기본생성자");
}
public TestClass09(String s) {
super(s);
System.out.println(s + " : 자식 생성자");
}
}
public class MainClass09 {
public static void main(String[] args) {
TestClass09 tc = new TestClass09("전달");
// 자식 클래스로 이동 > 부모 클래스로 이동
// super(); 를 통해 부모 클래스로 값을 전달했기 때문에
// ( 만약 super 를 사용하지 않았다면 부모의 기본 생성자가 실행된다 )
// 부모 클래스의 매개변수를 필요로 하는 생성자 실행 >
// 자식 클래스의 매개변수를 필요로 하는 생성자 실행
TestClass09 tc2 = new TestClass09();
// 자식 클래스로 이동 > 부모 클래스로 이동
// 부모 클래스의 기본 생성자 실행 > 자식 클래스의 기본 생성자 실행
// ( 매개변수가 없기 때문에 둘 다 기본 생성자가 실행되었음 )
}
}
부모 클래스의 매개변수를 전달하는 방법 : super();
private, protected
package inheritance;
class Test10{
// 상속을 받든지 말든지 자기 자신을 제외한 모든 접근을 차단
// private int num = 1000;
// 상속받은 자식 클래스는 접근을 허용
protected int num = 1000;
}
class TestClass10 extends Test10{
public int num = 12345;
public void test() {
System.out.println("num : " + num);
// 자기 자신의 변수 num 을 출력 후 없다면 부모 클래스의 num 탐색
System.out.println("this.num : " + this.num);
// 부모 클래스의 변수 num 을 탐색 -> 만약 num 변수가 없다면 컴파일 오류 발생
System.out.println("super.num : " + super.num);
}
}
public class MainClass10 {
public static void main(String[] args) {
TestClass10 tc = new TestClass10();
tc.test();
}
}
private 과 protected 의 차이점
다중 상속
package inheritance;
class A{
public void a() {
System.out.println("a 메소드 실행");
}
}
class B extends A{
// A 를 상속
public void b() {
System.out.println("bbbb 메소드 실행");
}
}
class C extends B{
// A 를 상속한 B 를 상속
public void c() {
System.out.println("cccccccc 메소드 실행");
}
}
public class MainClass11 {
public static void main(String[] args) {
// A 를 상속한 B 를 상속한 C 를 객체로 생성
C c = new C();
// 다중 상속을 통해 A, B, C 의 모든 메소드를 사용할 수 있다
c.a();
c.b();
c.c();
}
}
중복으로 상속하는 것은 class 에서는 불가능하기 때문에 여러번에 거쳐서 상속을 진행
실습 예제
실습 예제
이전에 만들었던 로그인 프로그램을 찾지 못하는 연유로 처음부터 코딩.....
package inheritance;
public class MainLogIn {
public static void main(String[] args) {
LogInService ls = new LogInService();
while(true) {
ls.mainPrint();
}
}
}
MainLogIn 클래스
package inheritance;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class LogInService extends java.util.Date {
Scanner sc = new Scanner(System.in);
LogInDTO DTO = new LogInDTO();
// 메인 메뉴
public void mainPrint() {
System.out.println("1. 로그인");
System.out.println("2. 회원가입");
System.out.println("3. 탈퇴");
System.out.print(">>> : ");
int choice = sc.nextInt();
switch(choice) {
case 1 : logIn(); break;
case 2 : createId(); break;
case 3 : removeId(); useTime(); break;
default :
System.out.println("입력 오류!!!");
break;
}
}
// 로그인
private void logIn() {
if(DTO.getId() == null) {
System.out.println("회원 등록부터 진행하세요!");
}
else {
System.out.print("아이디를 입력 : ");
String id = sc.next();
System.out.print("비밀번호를 입력 : ");
String pwd = sc.next();
checkId(id, pwd);
}
}
// 로그인 시 아이디 검증
private void checkId(String id, String pwd) {
if(DTO.getId().equals(id) && DTO.getPwd().equals(pwd)) {
System.out.println("!!! " + id + "님 로그인 완료 !!!");
// 로그인 완료 시 시간 저장
DTO.setStartTime(System.currentTimeMillis());
}
else System.out.println("회원정보가 올바르지 않습니다");
}
// 회원 생성
private void createId() {
if(DTO.getId() == null) {
System.out.print("아이디 입력 : ");
String id = sc.next();
System.out.print("비밀번호 입력 : ");
String pwd = sc.next();
DTO.setId(id);
DTO.setPwd(pwd);
System.out.println("회원가입이 완료되었습니다!");
}else {
System.out.println("이미 회원이 존재합니다. 삭제 후 진행하세요");
}
}
// 회원 삭제
private void removeId() {
DTO.setId(null);
DTO.setPwd(null);
System.out.println("회원 탈퇴가 완료되었습니다!!!");
// 회원 삭제 시간 저장
DTO.setEndTime(System.currentTimeMillis());
}
// 로그인 시간, 탈퇴 시간, 사용 시간 출력
private void useTime() {
SimpleDateFormat si = new SimpleDateFormat("yyyy년 MM월 dd일 aa hh시 mm분 ss초");
System.out.println("시작 시간 : " + si.format(DTO.getStartTime()));
System.out.println("종료 시간 : " + si.format(DTO.getEndTime()));
System.out.println("사용 시간 : " + ((DTO.getEndTime()-DTO.getStartTime()) / 1000) + "초");
}
}
LogInService 클래스
( java.util.Date 클래스를 상속받아 사용 날짜에 대한 정보를 저장 및 출력 )
package inheritance;
public class LogInDTO {
private long startTime, endTime;
private String id, pwd;
// getter / setter
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
package com.baseball;
public class Main {
public static void main(String[] args) {
while(true) {
BaseballService bb = new BaseballService();
int choice = bb.mainPrint();
bb.choiceNum(choice);
}
}
}
Main 클래스
package com.baseball;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;
public class BaseballService {
Scanner sc = new Scanner(System.in);
BaseballDTO DTO = new BaseballDTO();
Random ran = new Random();
public int mainPrint() {
System.out.println("★★★★★ 숫자 야구 ★★★★★★");
System.out.println("★ 1. 숫자 야구 플레이 ★");
System.out.println("★ 2. 종 료 ★");
System.out.println("★★★★★★★★★★★★★★★★★★");
System.out.print("번호 입력 >>> ");
int choice = sc.nextInt();
return choice;
}
public void choiceNum(int choice) {
switch(choice) {
case 1 : mainGame(); break;
case 2 :
System.out.println("프로그램을 종료합니다");
break;
default :
System.out.println("입력 오류 발생!!! 프로그램을 다시 실행하시오");
break;
}
}
public void mainGame() {
// 콘솔창 지우기
erasePrint();
// 숫자 야구 정답 생성 - DTO 클래스의 mainBall 에 저장
makeMainBall();
// 숫자 생성부분 시각화
makeView();
while(true) {
System.out.println("★★★★★★★★★★★");
System.out.println("★수를 예상하세요★");
System.out.println("★ ex)0125 ★");
System.out.println("★★★★★★★★★★★");
System.out.println("현재 도전 횟수 : " + DTO.getTryNum());
System.out.print("입력 >>> ");
String guessBall = sc.next();
try{
if(Integer.parseInt(guessBall) > 0 && Integer.parseInt(guessBall) < 10000) {
// 추측한 숫자를 guessBall 변수로 생성자를 통해 세팅
DTO.setGuessBall(guessBall.charAt(0), guessBall.charAt(1), guessBall.charAt(2), guessBall.charAt(3));
checkBall();
System.out.println("--- 추측 결과 ---");
System.out.println(" Strike : " + DTO.getStrike());
System.out.println(" Ball : " + DTO.getBall());
System.out.println("----------------");
System.out.println("다시 게임을 준비하는중.............");
timeSleep(5000);
// 정답을 맞춘 경우
if(DTO.getStrike() == 4) {
System.out.println("☆★☆★숫자를 모두 맞추셨습니다★☆★☆");
System.out.println("☆★ 총 도전 횟수 : " + DTO.getTryNum() + " ★☆");
System.out.printf("정 답 : %d %d %d %d\n",DTO.getMainBall(0), DTO.getMainBall(1), DTO.getMainBall(2), DTO.getMainBall(3));
break;
}
// 스트라이크와 볼 갯수 초기화
DTO.setBall(0); DTO.setStrike(0);
// 도전 횟수 증가
DTO.setTryNum(DTO.getTryNum() + 1);
}else {
System.out.println("!!!입력 오류!!!");
continue;
}
} catch(Exception e){
System.out.println("!!!입력 오류!!!");
continue;
}
}
}
// 콘솔 창 지우개
public void erasePrint() {
for(int i=0; i<=100; i++) System.out.println();
}
// 정답 생성
public void makeMainBall() {
int[] num = new int[4];
for(int i=0; i<4; i++) {
num[i] = ran.nextInt(10);
for(int j=0; j<i; j++) {
if(num[i] == num[j]) i--;
}
}
DTO.setMainBall(num[0], num[1], num[2], num[3]);
}
// a 초 만큼 코드 중지
public void timeSleep(int a) {
try {
Thread.sleep(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 난수 생성 시각화
public void makeView() {
for(int i=1; i<=4; i++) {
System.out.println("★★★★★★★★★★★★★★★★★★");
System.out.printf("★★★★%d번째 수 생성중★★★★\n", i);
timeSleep(1000);
for(int j=0; j<=7; j++)
System.out.println("★★★★★★★★★★★★★★★★★★");
timeSleep(500);
}
System.out.println("★★★★★★준비 완료★★★★★★");
System.out.println();
}
// Strike 와 Ball 갯수 체크
public void checkBall() {
for(int i=0; i<4; i++) {
if (DTO.getGuessBall(i) == DTO.getMainBall(i)) {
DTO.setStrike(DTO.getStrike() + 1);
}
for(int j=0; j<4; j++) {
if(DTO.getGuessBall(i) == DTO.getMainBall(j)) {
DTO.setBall(DTO.getBall() + 1);
}
}
}
}
}
BaseballService 클래스
package com.baseball;
import java.util.ArrayList;
public class BaseballDTO {
// 숫자 야구 정답
private int[] mainBall = new int[4];
// 추측 숫자
private int[] guessBall = new int[4];
// 정답이면 true, 정답이 아니면 false
private boolean ballCheck = false;
// 도전 횟수, ball, strike
private int tryNum = 0, ball = 0, strike = 0;
public BaseballDTO() {}
public int getMainBall(int i) {
return mainBall[i];
}
public void setMainBall(int num1, int num2, int num3, int num4) {
this.mainBall[0] = num1;
this.mainBall[1] = num2;
this.mainBall[2] = num3;
this.mainBall[3] = num4;
}
public boolean isBallCheck() {
return ballCheck;
}
public void setBallCheck(boolean ballCheck) {
this.ballCheck = ballCheck;
}
public int getTryNum() {
return tryNum;
}
public void setTryNum(int tryNum) {
this.tryNum = tryNum;
}
public int getGuessBall(int i) {
return guessBall[i];
}
public void setGuessBall(char num1, char num2, char num3, char num4) {
this.guessBall[0] = Character.getNumericValue(num1);
this.guessBall[1] = Character.getNumericValue(num2);
this.guessBall[2] = Character.getNumericValue(num3);
this.guessBall[3] = Character.getNumericValue(num4);
}
public int getBall() {
return ball;
}
public void setBall(int ball) {
this.ball = ball;
}
public int getStrike() {
return strike;
}
public void setStrike(int strike) {
this.strike = strike;
}
}
BaseballDTO 클래스
- 메모 -
1. 코드를 더 깔끔하게 정리하여 작성할 수 있는 방법이 무엇인지 생각하기
2. 현재 작성한 코드에 중복된 코드가 무엇인지, 추후에 공부하면서 보완할 내용은 무엇인지 꾸준하게 생각하기
package constructor;
public class MainClass {
public static void main(String[] args) {
TimeService ts = new TimeService();
ts.display();
}
}
MainClass 클래스
package constructor;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class TimeService {
Scanner sc = new Scanner(System.in);
TimeDTO DTO = new TimeDTO();
SimpleDateFormat si = new SimpleDateFormat("yyyy년 MM월 dd일 aa hh시 mm분 ss초");
String startTime, endTime;
int useTime;
// 기본 메뉴 출력
public void display() {
while(true) {
System.out.println("1. 시작 시간 설정");
System.out.println("2. 시작 시간 확인(년 월 일 시 분 초)");
System.out.println("3. 종료 시간 설정");
System.out.println("4. 종료 시간 확인(년 월 일 시 분 초)");
System.out.println("5. 사용 시간 가져오기");
System.out.print("선택 >>> ");
int choice = sc.nextInt();
switch(choice) {
case 1: startTime(); break;
case 2: showStart(); break;
case 3: endTime(); break;
case 4: showEnd(); break;
case 5: useTime(); break;
default : System.out.println("입력 오류!!!\n"); break;
}
}
}
// 시작 시간 설정
private void startTime() {
DTO.setStartTime(System.currentTimeMillis());
System.out.println("시작 시간 설정 완료");
}
// 시작 시간 출력
private void showStart() {
startTime = si.format(DTO.getStartTime());
System.out.println("시작 시간 : " + startTime);
}
// 종료 시간 설정
private void endTime() {
DTO.setEndTime(System.currentTimeMillis());
System.out.println("종료 시간 설정 완료");
}
// 종료 시간 출력
private void showEnd() {
endTime = si.format(DTO.getEndTime());
System.out.println("종료 시간 : " + endTime);
}
// 사용 시간 출력
private void useTime() {
// 시작시간이 종료시간보다 빠른 경우
if ( DTO.getEndTime() < DTO.getStartTime() ) {
System.out.println("시작 시간이 종료시간보다 빠를 수 없습니다.");
}
// 시작 시간이 설정되지 않은 경우
else if ( DTO.getStartTime() == 0 ) {
System.out.println("시작 시간을 설정해주세요");
}
// 종료 시간이 설정되지 않은 경우
else if ( DTO.getEndTime() == 0 ) {
System.out.println("종료 시간을 설정해주세요");
}
// 사용 시간 계산 후 출력
else {
double use = DTO.getEndTime() - DTO.getStartTime();
useTime = (int)(use / 1000);
System.out.println("사용 시간 : " + useTime + "초");
}
}
}
TimeService 클래스
package constructor;
public class TimeDTO {
private long startTime, endTime;
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
}
package constructor;
public class MemberMain {
public static void main(String[] args) {
MemberService mem = new MemberService();
mem.display();
}
}
MemberMain 클래스
package constructor;
import java.util.Scanner;
public class MemberService {
Scanner sc = new Scanner(System.in);
MemberDTO DTO = new MemberDTO();
// 메인 메뉴 출력
public void display() {
while(true) {
System.out.println("=== 학생관리 프로그램 ===");
System.out.println(" 1. 학생 등록");
System.out.println(" 2. 학생 보기");
System.out.println(" 3. 정보 수정");
System.out.println(" 4. 회원 탈퇴");
System.out.println("========================");
System.out.print("번호를 선택하세요 >>> ");
int choice = sc.nextInt();
switch(choice) {
case 1 : createStd(); break;
case 2 : showStd(); break;
case 3 : changeStd(); break;
case 4 : removeStd(); break;
default :
System.out.println("!!!입력 오류!!!");
break;
}
}
}
// 학생 정보 입력
private void createStd() {
System.out.print("이름 입력 >>> ");
String name = sc.next();
System.out.print("국어 성적 입력 : ");
int kor = sc.nextInt();
System.out.print("영어 성적 입력 : ");
int eng = sc.nextInt();
System.out.print("수학 성적 입력 : ");
int math = sc.nextInt();
DTO = new MemberDTO(name, kor, eng, math);
int sum = getSum(kor, eng, math);
char grade = getGrade(getSum(kor, eng, math));
DTO.setSum(sum);
DTO.setGrade(grade);
}
// 합 구하기
private int getSum(int kor, int eng, int math) {
return (kor + eng + math);
}
// 평균 구하기
private char getGrade(int sum) {
double aver = sum/3.0;
if (aver >= 90) return 'A';
else if (aver >= 80) return 'B';
else return 'c';
}
// 학생 정보 출력
private void showStd() {
if ( DTO.getName() != null) {
System.out.println("========= 학생 정보 =========");
System.out.println("이름 : " + DTO.getName());
System.out.println("국어 : " + DTO.getKor());
System.out.println("영어 : " + DTO.getEng());
System.out.println("수학 : " + DTO.getMath());
System.out.println("합 : " + DTO.getSum());
System.out.println("등급 : " + DTO.getGrade());
System.out.println("============================");
System.out.println();
}
else System.out.println("학생 정보를 등록 후 이용하세요.\n");
}
// 점수 변경
private void changeStd() {
if (DTO.getName() != null) {
System.out.println("\n===== 정보 수정 =====");
System.out.println("1. 이름 수정");
System.out.println("2. 국어 점수 수정");
System.out.println("3. 영어 점수 수정");
System.out.println("4. 수학 점수 수정");
System.out.println("====================");
System.out.print("선택하세요 >>> ");
int choice = sc.nextInt();
switch(choice) {
case 1 : changeName(); break;
case 2 : changeKor(); break;
case 3 : changeEng(); break;
case 4 : changeMath(); break;
case 5 :
System.out.println("!!! 입력 오류 !!!\n");
break;
}
System.out.println("!!! 변경 완료 !!!\n");
DTO.setSum(DTO.getKor() + DTO.getEng() + DTO.getMath());
DTO.setGrade(getGrade(DTO.getSum()));
}else System.out.println("학생 정보를 등록 후 이용하세요.\n");
}
// 이름 변경
private void changeName() {
System.out.print("변경할 이름 입력 : ");
String name = sc.next();
DTO.setName(name);
}
// 국어 변경
private void changeKor() {
System.out.print("국어 점수 입력 : ");
int kor = sc.nextInt();
DTO.setKor(kor);
}
// 영어 변경
private void changeEng() {
System.out.print("영어 점수 입력 : ");
int eng = sc.nextInt();
DTO.setMath(eng);
}
// 수학 변경
private void changeMath() {
System.out.print("수학 점수 입력 : ");
int math = sc.nextInt();
DTO.setMath(math);
}
// 학생 탈퇴
private void removeStd() {
if(DTO.getName()!=null) {
DTO = new MemberDTO();
System.out.println("!!!회원정보 초기화 완료!!!\n");
} else System.out.println("등록된 회원이 없습니다.\n");
}
}
MemberService 클래스
package constructor;
public class MemberDTO {
private String name;
private int kor, eng, math, sum;
private char grade;
public String getName() {
return name;
}
public MemberDTO(String name, int kor, int eng, int math){
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
public MemberDTO() {}
// getter / setter 생성
public void setName(String name) {
this.name = name;
}
public int getKor() {
return kor;
}
public void setKor(int kor) {
this.kor = kor;
}
public int getEng() {
return eng;
}
public void setEng(int eng) {
this.eng = eng;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public char getGrade() {
return grade;
}
public void setGrade(char grade) {
this.grade = grade;
}
}