Cloneable 복제해도 되는 클래스임을 명시하는 용도의 인터페이스다. Cloneable.java public interface Cloneable { // 실제로 이렇게 비어있음 } 하지만 신기한 점이 있는데, clone 메서드가 선언된 곳이 Cloneable이 아닌 Object이다. Object.java protected native Object clone() throws CloneNotSupportedException; 위 코드를 보면 clone() 메서드는 protected 접근 제한자를 가진다. 이렇게 되면 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메서드를 호출할 수 없다. 위 방법은 clone() 메서드를 오버라이드하여 public 접근제한자로 변경하여 외부 객체에서 접..
toString() 메서드 재정의 Object의 기본 toString 메서드는 PhoneNumber@adbbd처럼 단순히 클래스이름@16진수로 표시한 해시코드를 반환한다. 해당 인스턴스의 유익한 정보를 반환하기 위해서 toString 메서드는 재정의해야한다. 실전에서 toString은 그 객체가 가진 주요 정보 모두를 반환하는게 좋다. 따라서 toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공해야한다. PhoneNumber.java public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { t..
equals()와 hashCode() equals를 재정의한 클래스 모두에서 hashCode도 재정의해야한다. 그렇지 않으면 hashCode 일반 규약을 어기게 되어, 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. ▶ Object 명세에서 발췌한 규약 equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. equals가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. equals가 두 객체를 다르다고 판단 했더라도 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다...
equals() 메서드 재정의 equals 메서드 재정의는 간단해 보여도 함정이 많은 행위다. 문제를 회피하는 가장 좋은 방법은 아예 재정의를 하지 않는 것인데, 재정의를 하지 않으면 Object 클래스의 equals() 메서드를 호출하므로 그 클래스의 인스턴스는 오직 자기 자신과만 같게된다. ▶ 다음에서 열거한 상황 중 하나에 해당한다면 equals()를 재정의하지 말자. 1) 각 인스턴스가 본질적으로 고유하다. Object의 equals() 메서드가 이에 속한다. 2) 인스턴스의 '논리적 동치성(logical equality)'을 검사할 일이 없다. 논리적 동치성 5만원 지폐가 2개가 있을때, 각 지폐는 다른 지폐다. 하지만 금액은 같다. 어떤것을 비교하느냐에 따라 달라진다. 기본적으로 Object ..
Before. try~finally 자바 라이브러리에는 close 메서드를 호출하여 직접 닫아줘야하는 자원이 많다. 전통적으로 자원을 제대로 닫힘을 보장하는 수단으로 try~finally가 쓰였다. 더이상 자원을 회수하는 최선의 방책이 아니다. public class TopLine { // 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽) static String firstLineOfFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } }..
finalizer, cleaner 사용을 피하라 자바는 finalizer, cleaner이라는 두가지 객체 소멸자를 제공한다. 결론을 미리 말하자면, finalizer, cleaner 사용은 피해야한다. 두 객체 모두 즉시 수행된다는 보장이 없다. 객체에 접근할 수 없게 된 후 finalizer나 cleaner가 실행되기까지 얼마나 걸릴지는 알 수 없다. 때문에 제때 실행되어야 하는 작업은 절대 할 수 없다. finalizer, cleaner를 얼마나 신속하게 수행할지는 전적으로 가비지 컬렉터 알고리즘에 달렸으며, 이는 가비지 컬렉터 구현마다 각기 다르다. finalizer 구현 예제 finalizer 구현예제 public class FinalizerIsBad { @Override protected vo..
MongoDB를 사용하는 다른 방법 'MongoDB Altas Free버전 Compass 사용하기' 이전 포스팅을 참고하자. https://devfunny.tistory.com/850 [MongoDB] MongoDB Altas Free버전 Compass 사용하기 1) monggoDB 사이트 접속 https://account.mongodb.com/account/login?signedOut=true Cloud: MongoDB Cloud account.mongodb.com 2) 회원가입 후 로그인시, 접속되는 화면 3) create a database ■ [Build a Database] ■ [Create] ■ [Create Cluste devfunny.tistory.com Altas Free 버전 Compa..
예제로 보는 메모리 누수 자바는 가비지 컬렉터를 갖춘 언어이기 때문에 다 쓴 객체를 알아서 해제해준다. 이는 메모리 관리에 더이상 신경쓰지 않아도 된다고 오해할 수 있는데, 절대 사실이 아니다. 메모리 누수가 일어나는 위치는 어디인가? public class Stack { private Object[] elements; // 데이터를 쌓아놓는 경우, 언제 참조해제를 해야하는가?를 염두해야한다. private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { e..
Spring WebFlux Spring WebFlux는 리액티브 웹 애플리케이션 구현을 위해 Spring 5.0부터 지원하는 리액티브 웹 프레임워크다. 대량의 요청 트래픽을 Spring MVC 방식이 처리하지 못하는 상황이 잦아짐에 따라 적은 수의 스레드로 대량의 요청을 안정적으로 처리할 수 있는 비동기 Non-Blocking I/O 방식의 Spring WebFlux가 등장했다. Spring WebFlux 기술 스택 1) 서버 Non-Blocking I/O 방식으로 동작하는 Netty 등의 서버 엔진에서 동작한다. 2) 서버 API 기본 서버 엔진이 Netty이지만 Jetty나 Undertow 같은 서버 엔진에서 지원하는 리액티브 스트림즈 어댑터를 통해 리액티브 스트림즈를 지원한다. 3) 보안 WebFl..
Reactor의 디버깅 Reactor는 처리되는 작업들이 대부분 비동기적으로 실행되고, Reactor Sequence는 선언형 프로그래밍 방식으로 구성되므로 디버깅이 쉽지않다. Reactor에서는 디버깅을 할 수 있는 방법을 몇가지 제공한다. Debug Mode Debug Mode를 활성화해서 Reactor Sequence를 디버깅할 수 있다. @Slf4j public class Example12_1 { public static Map fruits = new HashMap(); static { fruits.put("banana", "바나나"); fruits.put("apple", "사과"); fruits.put("pear", "배"); fruits.put("grape", "포도"); } public st..
Context the situation, events, or onformation that are related to something and that help you understand it '어떤 것을 이해하는데 도움이 될만한 관련 정보나 이벤트, 상황'로 해석된다. 즉, Context는 어떠한 상황에서 그 상황을 처리하기 위해 필요한 정보라고 볼 수 있다. 프로그래밍 세계에서의 Context 예시 1) ServletContext는 Servlet이 Setvlet Container와 통신하기 위해서 필요한 정보를 제공하는 인터페이스다. 2) Spring Framework에서 ApplicationContext는 애프리케이션의 정보를 제공하는 인터페이스다. 3) Spring Security에서 Securi..
Thread 개념 이해 Reactor에서 사용되는 Scheduler Reactor Sequence에서 사용되는 스레드를 관리해 주는 관리자 역할을 한다. 컴퓨터 시스템에서 스레드는 물리적인 스레드(Physical Thread)와 논리적인 스레드(Logical Thread)로 구분된다. CPU의 코어(Core) 코어는 CPUD의 명령어를 처리하는 반도체 유닛이다. 일반적으로 코어의 개수가 많으면 더 많은 수의 명령어를 더 빠르게 병렬로 처리할 수 있다. 코어와 물리적인 스레드 관계 ▶ 물리적인 스레드 (Physical Thread) 하나의 코어는 두개의 스레드를 포함하고 있는데 이 두개의 스레드는 물리적인 코어를 논리적으로 나눈 것을 의미한다. 이렇게 물리적인 코어를 논리적으로 나눈 코어를 물리적인 스레드..
불필요한 객체 생성을 피하라 똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 재사용은 빠르고 세련되다. new String() 하지 말것 아래 코드를 보자. 쓰면 안되는 코드 String s = new String("bikini"); // 따라하지 말 것 위 코드는 실행될 때마다 String 인스턴스를 새로 만든다. 완전히 쓸데없는 행위다. 권장되는 코드 String s = "bikini"; 위 코드는 새로운 인스턴스를 매번 만드는 대신 하나의 String 인스턴스를 사용한다. JVM 안에서 이와 똑같은 문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용함이 보장된다. String.matches()를 사용할때 주의할것 생성 비용이 아주 비싼 객체가 있는데, 이..
Backpressure 리액티브 프로그래밍에서의 배압, 즉 Backpressure은 Publisher가 끊임없이 emit하는 무수히 많은 데이터를 적절하게 제어하여 데이터 처리에 과부하가 걸리지 않도록 제어하는 것이다. Publisher가 빠르게 데이터를 emit하는 경우 Subscriber의 처리속도가 느려서 처리가 끝나기도 전에 계속해서 emit하게된다. 이렇게되면 처리되지 않고 대기 중인 데이터가 지속적으로 쌓이게되어 오버플로가 발생하거나 최악의 경우에는 시스템이 다운되는 문제가 발생한다. 이 문제를 해결하기 위한 수단이 바로 Backpressure이다. Reactor에서의 Backpressure 처리 방식 첫번째 방법. Subscriber가 적절히 처리할 수 있는 수준의 데이터 개수를 Publis..
Cold와 Hot의 의미 지난 RxJava 공부 시기에 위 개념을 공부했었는데 다시보면 기억하기가 쉽지 않다. 리액티브 프로그래밍을 공부하면서 다시 나온 개념을 기억하고자 포스팅한다. Cold와 Hot의 의미를 모르는 사람은 없을 것이다. 대표적인 예시로 Hot Swapt이나 Hot Deploy를 보자. Hot Swap 컴퓨터 시스템의 전원이 켜져 있는 상태에서 디스크 등의 장치를 교체할 경우 시스템을 재시작하지 않고서도 바로 장치를 인식한다. Hot Deploy 서버를 재시작하지 않고서 응용 프로그램의 변경 사항을 적용한다. 공통점을 찾아보자. Hot은 무언가 처음부터 다시 시작하지 않고, 같은 작업이 반복하지 않는 느낌이다. 이와 반대인 Cold는 처음부터 새로 시작해야하고, 새로 시작하기 때문에 같..