[JAVA] 계산기 만들기2 - ArrayList, try-catch, Getter&Setter

림민지·2025년 3월 4일

Today I Learn

목록 보기
16/62

간단하게 계산기 기능을 구현했었는데, 여기서 더 발전된 코드로 개선했다.
<요구사항>
1. 클래스를 적용하기
2. 결과값을 저장하는 리스트 만들기
3. 캡슐화를 통해 결과값을 저장하고 있는 컬렉션에 직접 접근하지 못하도록 하기


1️⃣ 기존 코드 개선

while + case 문

기존 코드는 do-while로 작성했는데, 코드가 복잡했다.
그래서while문 과 case문을 활용하여 더욱 깔끔한 코드로 개선하기로 했다.

[기존 코드]

boolean 타입으로 true false를 통해 시스템을 유지할지 말지 결정해야했고, 불필요하게 else if (operator.equals("-")) 이러한 코드가 반복되었다.

import java.util.Scanner;

public class Calculator1Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in) ;
        boolean system = true;

        do {
            System.out.print("첫 번째 정수를 입력하세요 : ");
            int a = scanner.nextInt();
            System.out.print("두 번째 정수를 입력하세요 : ");
            int b = scanner.nextInt();
            System.out.print("사칙연산 기호를 입력하세요: ");
            String operator = scanner.next();
            if (operator.equals("+")) {
                add(a,b);
            } else if (operator.equals("-")){
                subtract(a,b);
            } else if (operator.equals("*")) {
                multiply(a,b);
            } else if (operator.equals("/")){
                divide(a,b);
            }
            System.out.println("더 계산하시겠습니까? 아무 문자나 입력하세요. (exit 입력 시 종료)");
            String ask = scanner.next();
            if (ask.equals("exit")){
                system = false;
                System.out.println("시스템을 종료합니다");
            }
        }while (system);

    }
    //더하기
    static void add(int a, int b){
        System.out.println("결과 : "+(a+b));
    }
    //빼기
    static void subtract(int a, int b){
        System.out.println("결과 : "+(a-b));
    }
    //곱하기
    static void multiply(int a, int b){
        System.out.println("결과 : "+(a*b));
    }
    //나누기
    static void divide(int a, int b) {
        if (b == 0) {
            System.out.println("수행할 수 없는 연산입니다");
        }else {
            System.out.println("결과 : "+(double) a/b);
        }
    }
}

그래서 코드 중복을 개선하고 더욱 깔끔한 코드로 바꾸기 위해 whilecase를 적극 활용하기로 했다.

package MakeCalculator1;

import java.util.Scanner;

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

        while (true) {
            System.out.print("첫 번째 정수를 입력하세요: ");
            int a = scanner.nextInt();
            System.out.print("두 번째 정수를 입력하세요: ");
            int b = scanner.nextInt();
            System.out.print("사칙연산 기호를 입력하세요: ");
            String operator = scanner.next();

            double result; // 연산 결과 저장

            switch (operator) {
                case "+":
                    result = add(a, b);
                    break;
                case "-":
                    result = subtract(a, b);
                    break;
                case "*":
                    result = multiply(a, b);
                    break;
                case "/":
                    result = divide(a, b);
                    break;
                default:
                    System.out.println("잘못된 연산 기호입니다. 다시 입력하세요.");
                    continue;  // 다시 입력 받도록 함
            }

            System.out.println("결과: " + result);

            System.out.println("더 계산하시겠습니까? 아무 문자나 입력하세요. (exit 입력 시 종료)");
            String ask = scanner.next();
            if (ask.equals("exit")) {
                System.out.println("시스템을 종료합니다.");
                break;
            }
        }
    }
    static int add(int a, int b) {
        return a + b; // 더하기
    }
    static int subtract(int a, int b) {
        return a - b;     // 빼기
    }
    static int multiply(int a, int b) {
        return a * b;    // 곱하기
    }
    static double divide(int a, int b) {
        if (b == 0) { 
            System.out.println("0으로 나눌 수 없습니다.");
            return 0; 
        }
        return (double) a / b;
    }
}

(1) while문으로 반복문을 실행하고, 만약 exit가 입력되었다면 break를 통해 반복문이 종료될 수 있도록 함
(2) case 문을 활용하여 불필요한 코드의 중복을 줄임.
(3) 연산 값을 저장하는 result변수 정의 -> 나중에도 활용될 수 있도록 함
(4) 연산 메서드를 void 에서 각각에 맞는 타입으로 변경
→ 값을 return함


2️⃣ 클래스를 적용하기

사칙연산을 수행 후, 결과값 반환 메서드 구현 & 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스를 생성해야한다.

1. CalculatorClass 클래스 만들기

위의 코드에서 사칙연산을 수행하는 부분을 클래스로 만들어서 사용해보자
먼저 CalculatorClass 클래스를 같은 패키지 안에 만들고 사칙연산을 수행하자

    //더하기
    int add(int a, int b){
        int result = a+b;
        return result;
    }

대표적으로 더하기 인스턴스를 보자. return값이 필요하므로 void가 아닌 반환 타입 int로 정의해 메서드를 만든다.

그리고 Main코드에CalculatorClass 클래스를 호출한다

CalculatorClass calculator = new CalculatorClass();

switch문에 calculator 클래스의 add함수를 호출하여 사용한다.

switch (operator) {
	case "+":
    	result = calculator.add(a, b);
        break;

클래스를 적용해 연산을 수행할 수 있다!


3️⃣ ArrayList

연산을 수행한 결과를 저장하는 컬렉션 필드를 만들자

ArrayList✨ :
배열은 크기가 고정되어 있어서 한 번 설정하면 길이를 변경할 수 없지만 ArrayList는 정해진 크기 없이 요소의 순서를 유지하고 중복된 값을 저장할 수 있는 자료구조입니다.

자바에서 List는 ArrayList로 구현할 수 있다.

import java.util.ArrayList;
...생략
ArrayList<Double> calculateList = new ArrayList<>(); 

<> 안에는 정의하고싶은 타입을 적는다.

ArrayListadd remove get키워드로 각각 추가, 삭제, 조회를 수행할 수 있다.

직접 더하기 메서드에 적용해보자

public class CalculatorClass {
    ArrayList<Double> calculateList = new ArrayList<>(); //연산 결과 저장하기

    //더하기
    int add(int a, int b){
        int result = a+b;
        calculateList.add((double) result); //calculateList 리스트에 저장
        return result;
    }

calculateList.add를 통해 연산 결과를 calculateList에 순서대로 저장할 수 있다.

4️⃣ try-catch

만약 코드에서 오류가 발생했다? 왜, 어디에서 발생했는지 알고 싶고, 오류가 발생했을때 수행할 로직을 정하고 싶다. 그럴때 try-catch문을 사용하면 된다!

예외란?

: 프로그램 실행 중 예상하지 못한 상황이 발생하는 것

  • 의도적으로 예외를 발생시킬 때는 throw 키워드를 통해 발생
  • 예외처리(try-catch)를 통해 프로그램이 안정적으로 실행되게 할 수 있다.

코드로 예시를 보면서 이해해보자
계산기 로직을 수행하면서 0으로 나누는 상황에서 예외가 발생할 수 있다.
→ 10 / 0 수행 시 오류 발생
이때 0으로는 나눌수없다고 경고문을 보여주면 좋지 않을까?

//나누기
   double divide(int a, int b) {
       if (b==0){
           throw new ArithmeticException("0으로는 나눌 수 없습니다");
       }
       double result = (double) a/b ;
       calculateList.add(result);
       return result;
   }

throw 키워드를 통해 만약 0으로 나누려고한다면 ArithmeticException 예외를 날려줘서 오류 문자를 띄울 수 있게 해줄 수 있다.
이를 적용한 main 코드를 보면

case "/":
	try { //0으로 나누었을때 연산 오류 잡기 try-catch로
    	result = calculator.divide(a, b);
        } catch (ArithmeticException e) {
        	System.out.println("오류! " + e.getMessage());
            System.out.println("다시 입력해주세요.");
            continue;  // 0으로 나누었을 경우 다시 입력 받도록 함.
            }
            break;

먼저 try로 result를 수행하면 클래스에서는 ArithmeticException을 날려준다.
이때 catch문이 System.out.println("오류! " + e.getMessage()); 로직을 수행한다.

5️⃣ Getter & Setter

: 클래스의 캡슐화(Encapsulation)를 위해 사용되는 메서드
→ 클래스 내부의 private 변수에 접근하고 수정할 수 있도록 해줌

1. Getter 메서드

: 객체의 private 변수 값을 외부에서 읽을 수 있도록 하는 메서드
get + 변수명 형식으로 메서드 이름을 작성

예시로 알아보자!

public class Person {
    private String name;  // private 변수 (직접 접근 불가)
    // Getter 메서드
    public String getName() {
        return name; // 변수 값 반환
    }
}
Person person = new Person();
System.out.println(person.getName());  // name 값을 가져옴

private 로 정의된 변수는 원래 외부에서 접근이 불가능하지만
getter를 사용하면 가져올 수 있다!

2. Setter 메서드

: 객체의 private 변수 값을 외부에서 변경할 수 있도록 하는 메서드
set + 변수명 형식으로 메서드 이름 작성

public class Person {
    private String name;  // private 변수
    // Setter 메서드
    public void setName(String name) {
        this.name = name;  // 받은 값을 변수에 저장
    }
}
Person person = new Person();
person.setName("홍길동");  // name 값 넣어주기

Setter를 사용하면 private로 정의된 변수값도 인자를 받아서 저장해줄 수 있다.

그럼 한번 계산기에 적용해보자

3. 계산기에 적용하기

계산기에 저장된 값을 private로 설정해 직접 접근하지 못하도록 보호하고, getter로 가져올 수 있도록 개선해보자!

(1) 먼저 ArrayList를 외부에서 직접 접근하지 못하게 private로 바꿔주자

private ArrayList<Double> calculateList = new ArrayList<>();

(2) main클래스에서 지금까지 저장된 연산의 수를 출력할 수 있도록 이를 반환하는 getter 메서드를 정의하자

int getListNum(){
	return calculateList.size();
    }

(3) main클래스에 불러오자

calculator.getListNum();
profile
@lim_128

0개의 댓글