
이번 주 왜 이렇게 피곤했는지 모르겠지만 이번주 내내 컨디션이 안 좋았다. 할건해야지,,
특히 네트워크 스터디 자료만드는데 정신 나갈뻔했다.
모든 객체는 Object를 상속한다. 그렇기 때문에 Object에서 정의한 함수들은 모든 객체에서 사용이 가능하다! 대표적으로 hashcode, equals, toString이 있다.
Objects.hashcode
- 객체가 생성될 때 생성되는 해시코드값을 반환합니다.
public static int hashCode(Object o) { return o != null ? o.hashCode() : 0; }
Object.hashcode
- 해당 메서드는 JNI를 사용해서 네이티브로 구현되어 있습니다.
@IntrinsicCandidate public native int hashCode();
Object.equals
- equals()가 true를 반환하는 두 객체는 항상 동일한 hashCode() 값을 반환해야 합니다.
public boolean equals(Object obj) { return (this == obj); }
Object.toString
- 클래스의 패키지네임 @hashcode값을 리턴합니다.
// OUTPUT java.lang.Object@2ff4acd0 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
Logging(이하 로깅)이란 애플리케이션 실행 중에 발생하는 이벤트나 로그 기록을 텍스트 형태로 콘솔에 출력하거나, 파일 등에 전달하여 저장하는 행위를 의미
로깅과 출력문의 차이 ?_?
- 로그는 레벨을 정할 수 있다. info,debug를 필요시마다 설정해서 로그를 볼 수 있다.
- 포매팅 할 수 있다.
log.info("USer 'guguttemy' Logged in");Handler
- 어디에다가 출력할지 결정하는 함수, 터미널 콘솔이나 파일, 네트워크를 통한 외부 서버의 DB에 저장하는 클래스
- 외부 서버는 Elastic search, redis 등을 언급하셨다.
Formatter
- 로그 메시지를 원하는 형태로 포매팅해주는 역할을 수행하는 클래스
Filter
- 개발자가 원하는 조건으로 로깅 처리 여부를 필터링할 수 있는 별도의 조건을 추가 가능한 인터페이스
// Logger.java
public void log(Level level, String msg) {
if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
doLog(lr);
}
Log의 내부코드 레벨이 안맞으면 리턴
Logger는 Slf4j가 상위의 인터페이스를 제공한다. 덕분에, Logger객체에 log4j나 Logback 객체를 선택해서 사용이 가능하다. 하지만, log4j가 먼저 등장했기 때문에, Slf4j와 log4j를 바인딩해주는 api를 또 설치를 해야한다.
https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j2-impl
함수형 인터페이스란 단 하나의 추상 메서드만 선언된 인터페이스를 의미함, 만약 Printer나 Parser같은 경우 비슷한 기능을 클래스로 정의하고 인자를 받아 처리하는경우가 많은데, 이때 유용하게 사용이 가능하다. 직접 구현체를 만들어서 사용하는게 아니라 객체와 람다로 처리가 가능하다.
public interface Calculator { int add(int a, int b); }제약조건
일반 인터페이스와는 다르게 함수형 인터페이스는 단 하나의 추상 메서드만 선언해야함
Calculator c2 = (int a, int b) -> a + b; 같이 인터페이스(Calculator c2)와
람다식 (int a, int b) -> a + b 이 1:1로 매칭이 불가능해짐 , 빼기로 해야할지 더하기로 해야할지 혼란이 옴
@FunctionalInterface
public interface Calculator {
int add(int a, int b);
int sub(int a, int b); // 컴파일 에러. Multiple non-overriding abstract methods found
}
개발자가 이러한 제약을 잘 준수하였는지 자바 컴파일러를 통해 확인시키기 위해서는 인터페이스 위에 @FunctionalInterface를 추가해주어야 함
@FunctionalInterface
public interface Calculator {
int add(int a, int b);
// int sub(int a, int b); // Multiple non-overriding abstract methods found
}
두 클래스는 동일하게 1과 2를 변경해주는 함수이다. 실제로 강사님께서 피드백해주신 내용은 이 두개를 함수형 인터페이스로 만들어보라고 하셨다.
public class DrinkParser { public static Drink parseDrink(int type) { if(type==1) return Drink.아메리카노; else return Drink.라떼; } }public class OrderTypeParser { public static OrderType parseOrderType(int type) { if (type == 1) { return OrderType.매장; } else return OrderType.테이크아웃; } }
변환 후
@FunctionalInterface public interface DrinkParserInterface { Drink parse(int type); } public class DrinkParser { public static DrinkParserInterface drinkParser = (type) -> { if (type == 1) return Drink.아메리카노; else return Drink.라떼; }; }public class Main { public static void main(String[] args) { // DrinkParser 사용 Drink drink = DrinkParser.drinkParser.parse(1); // 아메리카노 System.out.println(drink); // OrderTypeParser 사용 OrderType orderType = OrderTypeParser.orderTypeParser.parse(2); // 테이크아웃 System.out.println(orderType); } }
이후에 생생정호통(프로젝트 이름)에 백엔드 단을 추가할건데, 그 작업을 하기전에 자바콘솔로만 프로젝트를 진행해보았다.

순수 자바로 또, 콘솔로 프로젝트하는건 프리코스 찍먹 이후로 처음인데, 프리코스 할 때는 너무 귀찮고 불필요하다고만 느꼈는데 순수 자바로 프로젝트를 하려다보니까 더욱 플로우를 정리를 해야했고, 내가 필요한 모듈들을 다 구현하다보니 패키지 관리와 네이밍에 더욱 신경을 써야함을 느꼈다. 그리고 이전에 뒷줄의 요구사항을 콘솔로 구현하는 실습도 진행했었는데, 그때 입력값검증이 없어서 찬진님의 테스트?에 걸려 예외처리를 좀 신경쓰게 됐는데 이번 프로젝트에서는 미리미리 예외처리를 해두어서 정상적으로 잘 작동해서 뿌듯했다. 이 부분은 좀 더 학습이 필요한것 같다.
