Intro
오늘 한 일을 요약하자면, 알고리즘 풀고 java강의듣고 개인과제하기이다.
어제 듣던 자바를 마저 들었는데 다시 한번 자바를 다시 공부한 것에 감사를...
내가 가끔 '아 개념이 너무 부족한데, 처음부터 복습하자!'라고 하는 순간
while(true) { 처음부터 중간까지 공부하기 } 같이 무한루프로 초중반만 공부하기가 되어버려서...후반가면 개념이 약한게 느껴진다.
가장 최근에 들었던 김영한님의 자바 입문 수강한 내역....이 또한 입문이라 내용이 가볍다.
그래서 그런지 최근 강의듣는게 재미있다. 3주차까지 정리한 거밖에 없는데 총 44장 나와버리는 이 필기...
초반은 기본적인 것들에 주의해야하는 것들이나 한번 더 짚고 넘어가면 좋을 것들을 작성했었는데도
확실히 후반은 내용이 꽉 차있다보니 공부할 만한 내용들이 많았어서 좋다.
JAVA
* 이 챕터는 정리해둔 내용들을 복습하면서 적는 거라 구체적으로 작성X
상속
extends
자식 클래스의 멤버 개수는 부모 클래스보다 항상 같거나 많음.
자식 클래스는 부모 클래스로부터 물려받은 것을 자유자재로 사용할 수 있음.
- 상속관계, 포함관계
- 다중상속을 허용하지 않음.
- final 클래스와 final 메서드는 변경할 수 없음. 최종적인 클래스로써 더 이상 상속할 수 없는 클래스가 됨.
- Object 최상위 부모 클래스
오버라이딩
@Override
부모 클래스로부터 상속받은 메서드의 내용을 재정의 하는 것
super, super()
다형성, instanceof
다형성 - 여러 가지 형태를 가질 수 있는 능력
- 참고 변수의 타입 변환(자동 타입변환, 강제 타입변환)
+ 장점: 부모타입 객체로 통일할수있기에 객체를 교체해도 메인로직에 대한 변경이 필요가 없음
추상 클래스
abstract
미완성된 설계도
- 자식 클래스에 상속되어 자식 클래스에서 완성시킴(반드시 오버라이딩 되어야 함. interface와 다름)
인터페이스
interface
상속 관계가 없는 다른 클래스들이 서로 동일한 메서드를 구현해야 할 때 인터페이스는 구현 클래스들의 동일한 사용 방법과 행위를 보장해줄 수 있음.
public static final
public abstract (static x, default x)
인터페이스는 다중상속도 가능. 상속 시 extends
default. static
계산기 만들기
대망의 계산기 만들기 과제!! 오늘 처음 문제를 읽어보고 시작했다. 정말 많은 조건들이 있었는데 천천히 조건들에 맞게 구현하려 노력했다.
Lv 1.
가장 먼저 특정 조건을 많이 생각하지 않고 기본적으로 돌아가는 계산기를 만들었다.
예를들어 피연산자와 연산자를 넣으면 잘 계산은 되는데 만약 예외처리를 안한다면? 5 / 0 했을 때 에러가 나는데
그거를 콘솔로 표시해준다거나 하는 처리는 하지 않았다.
코드설명) 대략 코드 설명을 하자면 사용자가 연산자 입력 대신 "exit"을 작성하면 연산 무한 루프를 빠져나오는 방식이다. 계산은 이전에 계산했던거에 중첩해서 계속 계산해주는 방식이다. 더하기, 빼기, 곱하기, 나누기, 나머지를 구하는 연산만 메서드로 따로 분리하여 구현했다. 그리고 해당 연산자는 switch문으로 간단하게 메서드를 호출하는 방식으로 작성했다.
아래는 초기 버전
package calculator;
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long result = 0;
long realResult = 0;
while (true){
System.out.print("첫 번째 숫자를 입력하세요: ");
long operand1 = scanner.nextInt();
scanner.nextLine();
System.out.print("사칙연산 기호를 입력하세요: ");
String operator = scanner.nextLine();
if (operator.equals("exit")){
break;
}
System.out.print("두 번째 숫자를 입력하세요: ");
long operand2 = scanner.nextInt();
// 각각에 예외 처리 (양의 정수 2개, 0포함)
switch (operator){
case "+": result = add(operand1, operand2); break;
case "-": result = subtract(operand1, operand2); break;
case "*": result = multiply(operand1, operand2); break;
case "/": result = divide(operand1, operand2); break; // 두번째 숫자에 0이 들어오면 예외처리
case "%": result = remainder(operand1, operand2); break;
}
}
System.out.println("결과는 " + result);
}
static long add(long operand1, long operand2){
return operand1 + operand2;
}
static long subtract(long operand1, long operand2){
return operand1 - operand2;
}
static long multiply(long operand1, long operand2){
return operand1 * operand2;
}
static long divide(long operand1, long operand2){
return operand1 / operand2;
}
static long remainder(long operand1, long operand2){
return operand1 % operand2;
}
}
진짜 호다닥 작성한 코드라 쓸모없는 변수(realResult)도 있고 알고보니 연산자에 exit을 입력하게 해서 멈추는게 아니라 따로 계산이 끝나면 물어보는 조건이 있었어서 해당 부분들을 수정했다.
추가적으로 에러 처리를 가볍게 하기로 했다. 해당 에러처리를 나눗셈 메서드안에서 진행하고자 했다. 뒤에 입력한 숫자가 0이 되면 IllegalArgumentException 에러가 뜨도록 수정했다.
static long divide(long operand1, long operand2){
if (operand2 == 0){
throw new IllegalArgumentException("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
}
return operand1 / operand2;
}
static long remainder(long operand1, long operand2){
if (operand2 == 0){
throw new IllegalArgumentException("나머지 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
}
return operand1 % operand2;
}
1. 양의 정수(0도 포함)만 두개를 받아 계산
2. 연산자를 입력받으려해도 또 다른 입력값이 올 때
관련해서 if문으로 콘솔 메세지와 함께 while 무한루프를 중단하는 식으로 진행했다.
if ("+-*/%".indexOf(operator) == -1) {
System.out.println("해당 사칙연산은 현재 지원하지 않습니다. 다시 입력해주세요.");
break;
}
그리고 처음에 연산자를 String 타입으로 변수를 선언했는데, 굳이 String으로 자리 차지를 할 필요없을 거 같아서, char타입으로 변경하기도 했다. 대략 여기까지가 Lv 1이다.
Lv 2 .
레벨 2버전에서는 클래스를 분리하는 조건이 있었다. App클래스에서는 입력이나 출력을 담당하고 Calculator클래스에서는 계산들을 담당하여 역할을 구분했다. 사실은 입출력까지 따로 만들까도 생각했지만, 분리에 대한 필요성을 못 느껴 분리하지는 않았다.
Calculator 클래스는 연산 결과들을 컬렉션으로 저장하는 필드도 가지고 있어야 했고, 저장된 연산 결과들 중 가장 먼저 저장된 데이터를 삭제하는 기능을 가진 메서드를 구현하라해서 FIFO가 떠오르면서 Queue를 써보고 싶다는 생각이 들었다.
(결국 ArrayList로 만든 버전도 새로 만들어 버렸다....어떤 게 이 조건의 계산기 만들기 실습에서 더 좋은 지는 아직 모르겠다. 개인적으로는 ArrayList가 훨 나은 거 같지만 ㅎㅎ..)
평소 개발할 때 Queue로 컬렉션을 생성해본 적이 없다보니 일단 Calculator 클래스에 멤버 변수를 추가했다.
private Queue<Long> results = new LinkedList<>();
* 참고) Queue는 interface기 때문에 직접 인스턴스화 할 수 없다.
LinkedList는 Queue 인터페이스를 구현한 클래스기 때문에 이렇게 객체를 생성할 수 있다.
연산 결과들이 저장되어있는 컬렉션 필드를 App클래스에서는 마음대로 접근하지 못하게 private 접근 제어자로 캡슐화를 했다.
그리고 get과 set으로 간접 접근할 수 있게 작성했다.
public Queue<Long> getResults() {
return results;
}
public void setResults(long result) {
results.add(result);
}
이후 관련 계산하는 로직은 Lv1에서 했던 App에 있는 로직과 메서드들을 그대로 가져오면 되는거라 쉽게 마무리했던 거 같다.
이야기를 조금 추가하자면 ArrayList도 따로 만들었는데 간편하게 만들 수 있다.
private ArrayList<Long> results = new ArrayList<>();
public ArrayList<Long> getResults() {
return results;
}
public void setResults(long result) {
results.add(result);
}
다만 Queue같은 경우는 먼저 넣은 것을 먼저 뺀다는 자료구조를 가지고 있기 때문에 아예 poll()이라는 메서드로 FIFO 기능이 존재해서 results.poll()을 하면 된다. 그러면 값을 꺼냄과 동시에 삭제한다. ArrayList는 .remove()를 사용해서 첫번째 데이터를 그저 삭제해주면 된다.
// Queue
public void removeResult(){
results.poll();
}
// ArrayList
public void removeResult(){
results.remove(0);
}
알고리즘
알고리즘 풀이한 것은 아래 북마크 따라 들어가면 확인할 수 있다!
[알고리즘] 입문 모음4
자릿수 더하기풀이✅:import java.util.*;public class Solution { public int solution(int n) { int answer = 0; while (n > 0){ answer += n % 10; n /= 10; } return answer; }}이 코드로 작성하기 전에 여러 방식이 떠올랐다. int를 String
cinining.tistory.com