본문 바로가기

JAVA

[Java] Lv_2 계산기 프로젝트

 

요구사항

  • 사칙연산을 수행 후, 결과값 반환 메서드 구현 & 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스를 생성 
    • ⬜ 사칙연산을 수행한 후, 결과값을 반환하는 메서드 구현 ✅
    • ⬜ 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스를 생성 ✅
    • ⬜ 1) 양의 정수 2개(0 포함)와 연산 기호를 매개변수로 받아 사칙연산(➕,➖,✖️,➗) 기능을 수행한 후 2) 결과 값을 반환하는 메서드와 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스를 생성합니다. ✅
  • Lv 1에서 구현한 App 클래스의 main 메서드에 Calculator 클래스가 활용될 수 있도록 수정
    • ⬜  연산 수행 역할은 Calculator 클래스가 담당 ✅
      • ⬜ 연산 결과는 Calculator 클래스의 연산 결과를 저장하는 필드에 저장 ✅
    • ⬜  소스 코드 수정 후에도 수정 전의 기능들이 반드시 똑같이 동작해야합니다. ✅
  •  App 클래스의 main 메서드에서 Calculator 클래스의 연산 결과를 저장하고 있는 컬렉션 필드에 직접 접근하지 못하도록 수정 (캡슐화) 
    • ⬜ 간접 접근을 통해 필드에 접근하여 가져올 수 있도록 구현합니다. (Getter 메서드) ✅
    • ⬜ 간접 접근을 통해 필드에 접근하여 수정할 수 있도록 구현합니다. (Setter 메서드) ✅
    • ⬜  위 요구사항을 모두 구현 했다면 App 클래스의 main 메서드에서 위에서 구현한 메서드를 활용 해봅니다. ✅
  • ⬜ Calculator 클래스에 저장된 연산 결과들 중 가장 먼저 저장된 데이터를 삭제하는 기능을 가진 메서드를 구현한 후 App 클래스의 main 메서드에 삭제 메서드가 활용될 수 있도록 수정 ✅
    • 키워드 : 컬렉션 

 


 

 

문제 풀이

더보기

Calculator Class

package lv2;

import java.util.*;

public class Calculator {
    final private Queue<Object> resultList = new ArrayDeque<>();

    public void getResult() {
        System.out.println(resultList);
    }

    public void setResult(Object result) {
        if(result != null) resultList.add(result);
    }

    public void deleteNum() {
        try {
            resultList.remove();
        } catch (NoSuchElementException e) {
            System.out.println("저장된 값이 없습니다.");
        }
    }

    public Object calculate(int firstNum, int secondNum, char operator) {
        switch (operator) {
            case '+': {
                System.out.println(firstNum + " + " + secondNum + " = " + (firstNum + secondNum));
                return firstNum + secondNum;
            }
            case '-': {
                System.out.println(firstNum + " - " + secondNum + " = " + (firstNum - secondNum));
                return firstNum - secondNum;
            }
            case '*': {
                System.out.println(firstNum + " * " + secondNum + " = " + (firstNum * secondNum));
                return firstNum * secondNum;
            }
            case '/': {
                if (secondNum != 0) {
                    System.out.println(firstNum + " / " + secondNum + " = " + ((double) firstNum / secondNum));
                    return ((double)firstNum) / secondNum;
                } else {
                    System.out.println("0으로 나눌 수 없습니다.");
                    return null;
                }
            }
            default: {
                System.out.println("사칙 연산자를 입력해주세요.");
                return null;
            }
        }
    }
}

Calculator 클래스에서 Queue 컬렉션의 타입을 Object로 설정한 이유 :

  • calculate 메서드의 결과값이 정수형과 실수형 둘 다 나오는데, 이 두 가지 타입을 한 상자(Queue)에 담기 위해서이다.
  • Queue<Object>는 모든 객체 타입을 저장할 수 있다.
    1. 모든 클래스는 Object 클래스를 상속받고 있다.
    2. 부모 클래스는 자식 클래스를 담을 수 있다. (ex. Object obj = new child();)
    3. 즉, Object 타입 변수에는 어떤 참조형(클래스, 배열 등) 객체든 저장 가능하다.

 

Calculator Class의 calculate 메서드에서 각 연산자에 따른 반환 타입은 int와 double 2가지가 있다. 근데, calculate 메서드의 반환 타입은 Object이다. 어떻게 가능하지 살펴보자.

  1. 자바는 int, double을 Integer, Double이라는 객체로 자동으로 바꿔 줄 수 있다. (auto-boxing)
  2. Integer, Double은 Wrapper Class이다.
  3. Wrapper Class 역시 Object Class를 상속받고 있다.
  4. 부모 클래스는 자식 클래스를 담을 수 있다. (ex. Object obj = new child();)
  5. 즉, int, double이 오토박싱되어 Wrapper 객체로 변환된 후, Object 타입으로 반환된다.

 

 

더보기

App

package lv2;

import java.util.InputMismatchException;
import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Calculator calculator = new Calculator();

        while (true) {
            try {
                System.out.print("첫 번째 숫자를 입력해주세요 : ");
                int firstNum = scanner.nextInt();

                System.out.print("사칙 연산 기호를 입력해주세요 : ");
                char operator = scanner.next().charAt(0);

                System.out.print("두 번째 숫자를 입력해주세요 : ");
                int secondNum = scanner.nextInt();
                scanner.nextLine();

                if (firstNum < 0 || secondNum < 0) {
                    System.out.println("양의 정수만 입력하세요");
                } else {
                    Object result = calculator.calculate(firstNum, secondNum, operator);
                    calculator.setResult(result);
                }

            } catch (InputMismatchException e) {
                System.out.println("숫자만 입력해주세요!");
                scanner.nextLine();
            }

            try {
                System.out.print("저장된 결과값을 보시겠습니까? (y/아무 키 누르세요) ");
                if (scanner.nextLine().charAt(0) == 'y') {
                    calculator.getResult();
                }
            } catch (StringIndexOutOfBoundsException e) {}; 

            try {
                System.out.print("첫 번째 결과를 삭제하시겠습니까? (y/아무 키 누르세요) ");
                if (scanner.nextLine().charAt(0) == 'y') {
                    calculator.deleteNum();
                    calculator.getResult();
                }
            } catch (StringIndexOutOfBoundsException e) {};

            System.out.print("더 계산하시겠습니까? (exit 입력 시 종료) ");
            if (scanner.nextLine().equals("exit")) return;
        }
    }
}

StringIndexOutOfBoundsException 오류가 생기는 이유 :

  • 저장된 결과값을 보거나 결과를 삭제할 때, enter 키만 입력되는 경우 오류가 생긴다.
  • 조건문을 보면 scanner.nextLind().charAt(0)은 입력받은 문자열 중, 인덱스 0 번째  값을 가져온다는 것이다.
  • enter키만 입력받은 경우, 빈 문자 ""가 입력된다. 존재하지 않는 인덱스에 접근을 하려해서 오류가 생긴다.

 

'JAVA' 카테고리의 다른 글

[Java] 다이아몬드 상속  (0) 2025.04.19
[Java] toString()  (0) 2025.04.18
[Java] Lv_1 계산기 프로젝트  (0) 2025.04.17
[Java] 스트림(Stream)  (0) 2025.04.17
[Java] 익명 클래스란?  (0) 2025.04.17