[TIL] 계산기 프로젝트를 하며 배운 지식 3가지
TIL = Today I Learn, 직역하면 ‘내가 배운 것’을 정리하는 의미입니다
TIL을 작성해야 할 일이 점차 생기는 것 같으니 TIL 카테고리를 만들게 되었습니다
앞으로는 TIL 카테고리에 새롭게 배운 내용이나 마주했던 문제를 해결하는 방법에 대해 작성해보도록 하겠습니다
이번 TIL에서는 각 단계별을 진행하며 새로 배운 내용을 정리해보았습니다
첫 개인 프로젝트, 계산기 (Calculator)
링크 - 계산기 프로젝트 Repository
일주일의 개발 기간동안 JAVA 강의를 들으면서 프로젝트를 진행하였습니다
이 프로젝트를 통해 객체와 인스턴스, 스트림, 제네릭 등 다양한 기술을 적용해보았습니다
덤으로 브랜치를 나누어 개발하며 Git Merge를 하는 방법도 사용해보았구요
계산기 1단계 - try-catch-finally
IntelliJ를 설치하고 JVM, JDK 버전과 프로젝트 설정을 마친 뒤, 새로운 클래스를 만들어 간단한 계산기를 만들면 됩니다
다만, 예외 처리를 제대로 사용해보는 것은 이번이 처음이었기에 이 내용을 자주 찾아보게 되었습니다
1
2
3
4
5
6
7
8
9
10
11
12
// int num1 = 10;
// int num2 = 0;
try {
// 예외가 발생할 수 있는 코드 작성
int result = num1/num2;
System.out.println("num1 / num2 = " + result);
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다.");
} finally {
System.out.println("프로그램을 종료합니다.");
}
Java-Basic 카테고리에 아직 작성하지 않은 try-catch-finally 문법입니다
- try
- 예외가 발생할 수 있는 코드를 작성합니다
- 만약
try-catch를 작성하지 않은 채 위 예시처럼 0으로 나눌 경우 오류가 발생하게 됩니다 - try 문 안에 오류가 발생할 경우, try 문 코드 실행을 중지하고 catch 문으로 전달됩니다
- catch
- try 문에서 전달받은 경우, 0으로 나누면 생기는 예외인
ArithmeticException을 전달받으며 실행됩니다 - 예외 종류가 다양하기 떄문에 찾아보거나 코드를 실행하면서 출력되는 에러 발생 로그를 작성하면 됩니다
- 에러 종류가 다양할 경우
Exception를 작성하여 처리할 수 있습니다- (ArithmeticException은 RuntimeException을, RuntimeException은 Exception을 상속하고 있습니다)
- catch문을 여러번 작성할 수 있습니다
- try 문에서 전달받은 경우, 0으로 나누면 생기는 예외인
- finally
- 예외처리가 발생함의 여부에 상관없이 작동합니다
계산기 2단계 - switch expression
1단계는 App 클래스에서 모두 동작하도록 코드를 작성하였으나 2단계는 계산을 처리해주는 클래스를 만들어야 합니다
- Getter과 Setter를 통해 private 변수를 접근 및 조회할 수 있도록 설정
- switch 문을 통해 입력받은 연산 기호에 따라 계산 수행
- List 타입의
Results에 계산 결과들을 기록- 마지막으로 기록된 값을 지울 수 있도록 설정
2단계에서는 Java 12부터 추가된 새로운 switch expression을 사용하였습니다
1
2
3
4
5
6
7
8
String str = "A0";
int value = switch (str) {
case "A0", "A1" -> 10;
case "B0" -> 20;
case "B1" -> 21;
default -> -1;
};
이제는 값을 리턴받을 수 있으며, 람다식으로 값을 받으면 switch 문이 종료되기에 break를 작성할 필요가 없습니다
게다가 예시처럼 같은 값을 리턴하는 case를 여러번 적을 필요 없이 “,”로 구분지어 한 줄에 작성할 수 있습니다
단, 값을 리턴받는 switch 문을 작성할 경우
default를 반드시 정의해야 합니다
계산기 3단계 - Generic
3단계는 기본적인 내용으로 작성하던 1 ~ 2단계와 다르게
이넘, 람다, 스트림, 제네릭 등을 사용해야되기 때문에 난이도가 조금 더 높은 편입니다
여기서 제네릭 타입을 새로 알게 되었으니 한 번 알아보도록 하겠습니다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyClass<T extends Number> {
public void print(T num) {
System.out.println("print number : " + num);
}
}
public class Main {
public static void main(String[] args) {
MyClass<Integer> myClass = new MyClass<>();
myClass.print(10);
}
}
클래스 뒤에 <T extends Number>을 작성하였으며
Main에서 MyClass 객체를 만들 때 <Integer>을 붙여 타입이 Integer로 지정된 것을 볼 수 있습니다
이렇게 작성을 할 경우, 의도와 다르게 잘못된 타입을 사용하는 것을 방지할 수 있습니다
그리고 외부에서 타입을 지정해주기 때문에 String, Double으로 사용하는 등 클래스의 재사용성이 높아집니다
Generic의 특징
Reference Type만 사용 가능
아마 List를 사용해본 적이 있다면Integer,Double을 써야한다는 것에 의문을 품어보았을겁니다
int, double과 같은 원시 타입(Primitive Type)은 이전 버전의 JVM과의 하위 호환성을 위해서입니다Generic의 불공변성
만약MyClass<Integer>를 작성하였다면MyClass<Double>처럼 다른 타입으로 변환할 수 없습니다
하지만 이런 특징으로 인해 문제점이 생기는 경우 다른 방법으로 응용하는 것을 찾아봐야 합니다타입 기호 네이밍
꼭 “T”를 작성해야 하는 것은 아니지만 일반적으로 약속된 네이밍을 사용할 것을 권장합니다
Type(T), Element(E), Key(K) 등등이 있습니다