개발환경 - IndelliJ IDEA / JDK 17
Scanner input = new Scanner(System.in);
// 사칙연산 기호 입력받기
System.out.print("사칙연산 기호를 입력하세요: ");
char operator = input.charAt(0)
System.out.println("operator = " + operator);
구현 조건에 charAt 메서드를 사용하라는 조건이 있어서 코드에 구현했는데, charAt 메서드를 사용할 수 없다는 에러가 떴다.
그 이유는 Scanner 클래스가 해당 메서드를 제공하지 않기 때문
이었다.
해결 방법으로는 아래와 같다.
input.next()
로 문자열로 입력받는다.char operator = input.next().charAt(0);
그 이유는 아래와 같다고 한다.
char는 2바이트
를 사용하지만, String은 더 많은 메모리를 사용char는 기본 데이터 타입
으로, 비교 연산 시 '==' 연산자
를 사용하여 직접 값을 비교할 수 있습니다. 반면 String은 객체이므로 equals() 메소드를 사용단일 문자
이므로, 문자를 표현하는 데 특화된 char 타입이 더 적합System.out.print("첫 번째 숫자를 입력하세요: ");
int num1 = input.nextInt();
System.out.println("num1 = " + num1);
계산을 시작합니다. 종료하려면 'exit' 을 입력하세요.
계속하려면 아무 키나 누르세요(종료: exit)첫 번째 숫자를 입력하세요: e
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at calculator.Calculator.main(Calculator.java:22)
Process finished with exit code 1
내가 정수 대신 문자 'e' 를 입력했기 때문
에 입력 불일치 에러가 났다.
나는 숫자 입력시 예외 처리
를 추가하는 조치 + 유효한 숫자가 입력될 때까지 반복
하여 요청하는 조치를 취했다.
nt num1 = 0, num2 = 0;
boolean validInput = false;
// 첫 번째 숫자 입력
while (!validInput) {
System.out.print("첫 번째 숫자를 입력하세요: ");
try {
num1 = Integer.parseInt(input.nextLine());
validInput = true;
} catch (NumberFormatException e) {
System.out.println("유효한 숫자를 입력해주세요.");
}
}
System.out.println("num1 = " + num1);
// 두 번째 숫자 입력
validInput = false;
while (!validInput) {
System.out.print("두 번째 숫자를 입력하세요: ");
try {
num2 = Integer.parseInt(input.nextLine());
validInput = true;
} catch (NumberFormatException e) {
System.out.println("유효한 숫자를 입력해주세요.");
}
}
System.out.println("num2 = " + num2);
이렇게 했더니 첫 번째 숫자나 두번째 입력칸에 숫자가 아니라 문자를 입력해도 알고리즘이 진행해버리는 에러
가 발생했다.
정수를 입력하면 다시 입력하라고 돌아갔다...
이것은 두 번째 숫자 입력 부분에서 validInput 변수를 재설정하지 않은 오류
였다.
int num1 = 0, num2 = 0;
boolean validInput; // <-- 변경: 여기서 초기화 되지 않음
// 첫 번째 숫자 입력
validInput = false; // <-- 변경: 여기서 false 로 설정
while (!validInput) {
System.out.print("첫 번째 숫자를 입력하세요: ");
try {
num1 = Integer.parseInt(input.nextLine());
validInput = true;
} catch (NumberFormatException e) {
System.out.println("유효한 숫자를 입력해주세요.");
}
}
System.out.println("num1 = " + num1);
// 두 번째 숫자 입력
validInput = false; // <-- 변경: 두 번째 숫자 입력 전 다시 false로 설정
while (!validInput) {
System.out.print("두 번째 숫자를 입력하세요: ");
try {
num2 = Integer.parseInt(input.nextLine());
validInput = true;
} catch (NumberFormatException e) {
System.out.println("유효한 숫자를 입력해주세요.");
}
}
System.out.println("num2 = " + num2);
두 번째 숫자 입력 전에 validInput = false;로 재설정하여 문제를 해결했다.
exit 을 'EXIT' 으로 대문자로 입력했을 경우 계산기가 종료되지 않는 버그가 있었다.
if(continueInput.equalsIgnoreCase("exit")) {
break;
}
해당 버그는 equalsIgnoreCase()
를 사용하여 대소문자 구분 없이 "exit"를 인식하도록 했다.
대소문자 구분 없이 문자열을 비교하여 계산기를 종료하려했으나...
exit 이나 EXIT 을 입력해도 계산기가 종료되지 않는 버그
가 발생했다.
System.out.print("계속하려면 아무 키나 누르세요(종료: exit): ");
String continueInput = input.nextLine();
println()은 줄 바꿈을 포함하기 때문에, 사용자 입력이 새 줄에서 시작되어 빈 문자열로 인식
되어 나는 에러라고 한다.
System.out.print("계속하려면 아무 키나 누르세요(종료: exit): "); // println()을 print()로 변경
print() 를 사용했더니, 사용자 입력이 같은 줄에서 이어지므로, 입력한 'exit' 이 정확히 인식
되어 프로그램이 정상적으로 종료되었다.
System.out.println("계산을 시작합니다. 종료하려면 'exit'을 입력하세요.\n");
System.out.print("계속하려면 Enter 키를 누르세요(종료: exit): ");
String continueInput = input.nextLine().trim();
가독성을 위해 문자 제일 끝에 \n
개행문자를 삽입했더니,
아무 키도 누르지 않았음에도 첫번째 숫자를 입력하라는 시스템 메시지가 출력됐다.
이 문제는 입력 버퍼에 남아있는 개행 문자 \n 때문에 발생
한다고 한다.
이전 계산 후 사용자가 Enter 키를 눌러 결과를 확인하면, 그 Enter 키 입력이 다음 루프의 첫 번째 입력으로 처리되어 버린다고 한다 ....
System.out.println("\n계산을 시작합니다. 종료하려면 'exit'을 입력하세요.");
System.out.print("계속하려면 Enter 키를 누르세요(종료: exit): ");
String continueInput = input.nextLine().trim(); // trim()을 추가하여 앞뒤 공백 제거
문제 해결 방법은 다음과 같다.
연산 결과를 저장하는 컬렉션 타입 필드를 만들었다.
<Integer> 타입
을 사용하여 정수형 결과를 저장하고, 생성자에서 초기화
하여 항상 빈 리스트로 시작한다.
이유는 다음과 같았다.
List<> 로 리턴하는 것은 방어적 복사가 이루어지지 않는다고 한다.
원본 리스트의 참조를 그대로 전달하게 되어, 반환된 리스트를 수정하면 원본에도 영향을 준다.
이 메서드는 Public 이지만, 여전히 캡슐화의 원칙을 유지하고 있다.
이유는 다음과 같다.
Java 의 다형성 개념
이 적용되는 것 같다.
: 코드의 유연성과 재사용성을 높이는 객체지향 프로그래밍의 중요한 원칙
new ArrayList<>(results)
는 ArrayList 객체를 생성하지만, 이 객체는 List 인터페이스 타입으로 반환됨List<Integer>
으로 선언되어 있으므로, 실제로는 ArrayList 객체를 생성하지만 이를 List 타입으로 반환
하는 것임주로 정수를 0으로 나누려고 할 때 발생
RuntimeException 의 하위 클래스
로, 체크되지 않는 예외(unchecked exception)
이다.매개변수가 허용되지 않는 값을 가질 때 사용됨
RuntimeException 의 하위 클래스
로, 체크되지 않는 예외(unchecked exception)
이다.문자가 포함된 문자열
을 변환하려 할 때범위를 초과하는 값
을 변환하려 할 때빈 문자열
이나 공백
만 있는 문자열을 변환하려 할 때null
을 변환하려 할 때Enum
Enum vs Class ?
확장이 얼만큼 진행되는가?
기준으로 선택빌드를 다시 해야함
vs Class 는 사용자의 input 으로 객체를 새로 생성할 수 있음
Interface vs Class ?
공통 로직이 있는가?
기준으로 선택동작 방식
만 맞추려면 Interface vs 구현체
가 있어야 한다면 Class다중상속
가능한 Interface vs 단일상속
만 가능한 Class"!"는 인지가 잘 되지 않기때문에 ignore 함수(equalsIgnoreCase)
를 사용하는 것이 훨씬 좋음
continueInput.equalsIgnoreCase("exit") !== "exit".equalsIgnoreCase(continueInput)
NullPointException
발생 유무가 다름DTO
를 이용해 값을 넣어주면 양질의 코드 작성 가능javaDoc
을 검색해보기! 주석 형태 있음!JDK 버전, 목적, 주요 기능, 개선 사항
등을 적기
- Java 언어 소스 코드에서 "프로그램을 설명하는 문서"를 생성하는 메커니즘
- JDK가 설치 되어있다면 Javadoc 사용 가능
- MVC 패턴으로 개발하는 방식에서 다른 클래스에서 메소드를 호출하는 경우가 많아 사용하기 편리