백만년 만에 쓰느 포스팅...
지난 주는 Java강의를 들으며 숙제와... 과제2level까지 를 했다..
이번주는 지난주에 이어 level3을 했지만 제네릭 사용하는 부분이...좀...
강의에 제네릭이 너무 짧게나와 어떻게 적용시켜야할지 애먹었던거같다..
Level1
클래스는 메인 클래스 하나
오르지 숫자2개와 연산자를 입력받아 조건문을 사용해 바로 연산결과 출력
Level2
메인클래스인 App클래스와
연산을 담당하는 Calculator클래스로 구분
App클래스에서는 사용자의 입력값을 받고 출력함.
Calculator클래스에서는 연산과 큐에 연산결과를 저장 및 수정(저장된 맨 앞의 결과 삭제)
이때, 모든 수는 int 정수형으로 계산함(입력과 연산결과 모두 정수형)
Level3
메인클래스인 App클래스와
계산된 결과를 저장 및 수정하는 Calculator,
실질적 연산을 담당하는 열거형 클래스 Operator,
입력된 수를 정수인지 실수인지 판별하는 Parser클래스가 있다.
메인 App클래스는 은 Lev2와 같지만 입력값을 정수가 아닌 문자열로 받는다.
해당 문자열은 Parser클래스에서 입력된 문자열인 정수인지, 실수인지 확인 후 리턴한다.
public Number parseNum(String input) {
if (Pattern.matches(NUMBER_REG, input)) {// 숫자가 맞는지 판별
if (isInteger(input)) { // 입력값이 정수형이면 정수형으로 리턴
return Integer.parseInt(input);
}else if (isDouble(input)) { // 입력값이 실수형이면 실수형으로 리턴
return Double.parseDouble(input);
}
}
return null;
}
public static boolean isInteger(String input) {
try {
Integer.parseInt(input);
return true;
} catch (NumberFormatException e) {
return false;
}
}
그리고 연산을 담당하는 클래스는 열거형 클래스(실제 클래스는 아니지만 클래스처럼 작동이 가능)에서 연산
열거형은 이번에 새롭게 배웠다. 열거형은 고정된 상수의 집합을 정의한다.
public enum Operator { //Enum을 클래스 처럼 사용가능
PLUS('+') {
@Override
public Number calOper ( Number firNum, Number secNum){
double result = firNum.doubleValue() + secNum.doubleValue(); // 계산 결과를 먼저 실수형으로 저장.
if (result % 1 == 0) {// 나머지가 0이면 정수형으로 저장
int intResult = (int) result;
System.out.println(firNum + " + " + secNum + " = " + intResult);
return intResult;
} else {
System.out.println(firNum + " + " + secNum + " = " + result);
return result;
}
}
},
위와 같이 연산후 연산결과(정수 또는 실수)를 반환한다.
그리고 연산결과를 큐에 저장하는 Calculator클래스에서 저장 및 삭제, 필터링을 한다.
public T calculate(char oper, Number firNum, Number secNum) { // 연결결과 리턴
if (oper == Operator.PLUS.getSymbol()) {
return (T) Operator.PLUS.calOper(firNum, secNum);
} else if (oper == Operator.MINUS.getSymbol()) {
return (T) Operator.MINUS.calOper(firNum, secNum);
} else if (oper == Operator.MULTIPLY.getSymbol()) {
return (T) Operator.MULTIPLY.calOper(firNum, secNum);
} else if (oper == Operator.DIVIDE.getSymbol()) {
return (T) Operator.DIVIDE.calOper(firNum, secNum);
}
return null;
}
연산 결과를 제네릭을 사용해 T로 형 반환 후
public void setResult(T result) { //연산결과 저장
this.result.add(result);
}
를 이용하여 큐에 저장한다 이때 정수면 정수, 실수면 실수로 저장된다.
그리고 저장된 결과값들 중 사용자가 입력한 수 이상인 결과값들을 출력하는 메소드는 스트림을 사용하였다.
public void getFilter(Number input) { // 입력한 수 보다 큰 수를 조회
double min=input.doubleValue();
Number maxValue = result.stream()
.max(Comparator.comparingDouble(Number::doubleValue))
.get();// 저장된 계산 결과중 최대값을 가져옴
if (!result.isEmpty()) {
List<Number> filterList = result.stream()
.filter(number -> number.doubleValue() >= min)
.collect(Collectors.toList());// 입력한 수보다 큰 수들을 List에 넣음
if (filterList.isEmpty()) {
System.out.println("입력한 수가 저장된 최댓값보다 큽니다. 최대값: " + maxValue);
} else {
System.out.println(filterList);
}
} else {
System.out.println("저장된 계산 결과가 없습니다.");
}
}
이번 과제를 하면서 열거형, 스트림, 제네릭 부분을 새로 학습하게 되었지만.. 100% 이해했다고는 못하겠다..
실제로 어떤곳에 어떻게 쓰이는지를 안써보기도 헀고 특히 이번 과제에서 제네릭을 어디에 어떻게 적용해야될지 모르겠다. (일단 하래서 어떻게든 했는데 이게 맞나 싶다)
트러블 슈팅..
제네릭을 쓰는 이유는 사용자 입력값과 결과 출력값이 정수형인지 실수형인지 모르기 때문인데 여러곳에 적용해보려했으나 열거형은 클래스가 아니므로 제네릭을 사용하기 어려웠고, T타입으로 형변환이 안되는 부분이 많았다. 각 클래스의 매소드끼리 서로 참조하는 부분이 많아 쓰는데 많이 제한적이었다. 그래서 그냥 Number형으로 했더니 모든게 해결되었다..
이번과제에서 제네릭 없이 바로 Number만 써도 될듯..ㅎ
그리고 열거형클래스에 추상 메소드를 먼저 정의 후 그 밑에서 오버라이딩해서 사용하려고했는데 에러가 나서 찾아보니
열거형은 상수 객체를 정의하는 특별한 클래스 이기 때문에 상수가 필드나 메서드 보다 먼저 정의되어야 한다고 한다.
(고마워gpt 너없으면 이유도 못찾고 포기했을거야)
그래서 모든 메서드와 필드를 객체(상수)선언 (생성) 후 해줬더니 해결되었다.
그리고 사실 Number형을 쓰기 전에는 어떻게 입력값을 처리하고 저장하는지 몰랐는데
같이 공부하는 사람에게 물어보니 Number형을 스면 정수도 되고 실수도 된다는 이상한 말?ㅋㅋ 을 들었따..
그게 먼소리지 했는데 그분이 간단한 예시를 보여줬는데 신세계랄까? 와... 이렇게 쓸수있구나~ 했다
특히 그분은 List<Number> 로 하셨는데 이렇게 하면 리스트에 정수형도 넣을 수 있고 실수형도 넣을 수 있다는것을 처음 알았다. 그래서 난 Queue<Number>를 사용했더니 정수도 실수도 너무 잘들어간다!!
또 스트림 부분도 거의 처음 배우는 거라 검색도하고~ 지피티도 쓰고(99.99%)~ 해서 스트림을 적용해보았다.
배열(리스트) 에서 필터링 하거나, 출력,필요한 값 조회 등 할때 복잡한 반복문 여러개 쓰지 않고도 스트림과 람다식을 이용해 짧게 쓸수 있다니 너무너무 편리한거같다. 스트림 쵝오 ㅎ 근데 모르는게 많아 검색하면서 써야겠다..
강의내용에 제네릭,열거형,스트림 부분이 좀더 자세하게 나왔으면 하는 바램이 컸지만... 결국 검색과 지피티로 과제를 풀었다 ㅠ.. 사실 개발자도 이렇게 할텐데...? 100%다 외우고 알필욘 없자나? 럭키비키자나? 한잔해~
아 깃 리드미 쓰는것도 첨 배움.. 마크다운언어? 라는데 참 귀차는듯.. 벨로그 쓰는 사람 칭찬해~ 대단해~