Language/Java 56

CompletableFuture 검토해보기! (+ 발송 실패처리)

검토 이유 (Java, SpringBoot) 메일 서비스에서 발송 실패에 대한 처리가 필요했다. 해당 부분 Event를 사용하려고 했는데 팀장님께서 다른 곳에서는 Future를 사용한다고 하셔서 검토를 해보게 되었다. (InfraStructure에서 Domain Event를 발행하면 추적이 어려울 것 같다고 하셨다!) CompletableFuture 이해 Java에서 비동기 작업의 처리 결과를 반환받을 수 있는 방법이 없을까? Java 5 버전에는 Future라는 인터페이스가 추가되면서 비동기 작업에 대한 결과를 반환 받을 수 있게 되었다. 단, 아래의 한계가 있었다. 외부에서 완료시킬 수 없다. 블로깅 코드(get)를 통해서만 이후의 결과를 처리할 수 있다. 여러 Future를 조합할 수 없다. 예외 ..

Language/Java 2023.02.17

JAVA - 문자열 비교에서의 시간 복잡도

삼성에서 주관하는 알고리즘 특강에서 라빈-카프 알고리즘에 대해서 배웠다. 그런데 한 가지 의문 사항이 생겼다. 문자열을 equals로 비교하는 것이 O(1)일텐데 왜 굳이 해시로 바꿔서 비교를 해야 하냐는 것이었다. (밑에 작성했지만 이는 사실이 아니었다!!) String.Equals String 인스턴스의 equals 메서드를 살펴봤다. (JDK 13 기준) 해당 메서드에서는 StringLatin1.equals() 메서드를 호출하고 있다. StringLatin1.equals() 메서드를 보자! bytes 배열 요소를 전부 비교하고 있음을 알 수 있었다. 참고로 String의 value 타입은 Jdk 버전마다 구현이 다르다. jdk 8의 경우에는 아래와 같이 char 배열을 사용하고, 아래와 같이 비교하..

Language/Java 2023.02.14

Java - 불변 객체(Immutable Object) 사용을 지향해야 하는 이유! (feat. final 키워드)

Clean Code나 Effective Java는 물론이고, 개발을 잘하는 팀의 얘기를 들으면 불변(Immutable) 객체의 필요성이 빠지지 않는다. 왜 불변 객체가 중요한 지 알아보자. 불변(Immutable) 객체 불변 객체란 객체 생성 이후 내부의 상태가 변하지 않는 객체이다. 가령 JPA에서 Embedded로 사용하는 Value Object를 예로 들 수 있다. @EqualsAndHashCode public class Money { private int value; public Money(int value) { this.value = value; } public int getValue() { return value; } public Money multiply(int multiplier) { re..

Language/Java 2022.11.11

Java - String Constant Pool이란 무엇일까?

Java에서 String 객체를 생성하는 방법은 크게 2가지가 있다. String literal(큰 따옴표 " ") new 연산자 방법 비교 String str1 = "abcd"; String str2 = "abcd"; System.out.println(str1 == str2); // true String literal을 사용하면 동일성 비교를 할 때 true가 나온다. String str1 = new String("abcd"); String str2 = new String("abcd"); System.out.println(str1 == str2); // false new 연산자로 생성한 String에 대해서 동일성 비교를 하면 false가 나온다. 우선 동일성(==)에 대해서 알고 가자. 동일성은 두 ..

Language/Java 2022.11.09

Java - ThreadLocal 동작 원리 이해하기! (+ 주의사항)

지난 번에 샤딩을 앱 서버에서 처리하기 위해 ThreadLocal이라는 공간에 매핑될 DB 서버 정보를 넣어줬다. https://jaehoney.tistory.com/180 그렇다면 ThreadLocal은 도대체 어떻게 동작하는 걸까..? 자세히 알아보자. ThreadLocal ThreadLocal은 java.lang에서 지원하는 클래스로 Thread-Safety하다고 알려져있다. 나는 'ThreadPool의 각 Thread는 ThreadLocal이라는 공간을 가진다. ThreadLocal은 하나의 인스턴스로 접근할 수 있고, 멀티 쓰레드 환경에서도 안전하게 동작한다.' 정도로 이해했었다. 그런데 어떻게 그런 것이 가능한 지 의문이 있었다. ThreadLocal 내부를 분석해보면 ThreadLocalMa..

Language/Java 2022.11.06

JVM - GC 알고리즘 알아보기! (feat. JDK 버전 별 Default)

나는 Java 버전을 고를 때 주로 LTS 버전(현재 기준 17)을 선호한다. 그렇다면 해당 버전(17)에서는 JVM의 Garbage Collection(GC)가 어떤 식으로 동작할까? docker run --cpus=1 --rm -it eclipse-temurin:17 java -Xlog:gc* -version [0.004s][info][gc] Using Serial docker run --cpus=2 --rm -it eclipse-temurin:17 java -Xlog:gc* -version [0.007s][info][gc] Using G1 JDK 17 버전 기준으로는 CPU가 1개라면 Serial GC가 실행되고, CPU가 2개 이상이라면 G1 GC가 실행된다. (사실 JDK 9 버전 이후로 동일하..

Language/Java 2022.11.06

Java - 배열(Array)을 사용할 때 주의해야 할 점! [+ 공변(Convaiant)]

나는 배열과 리스트의 차이가 '자원 공간이 동적인지의 여부'로 생각해왔다. 그래서 자원 공간이 정해져있는 경우에는 배열을 사용했고, 그렇지 않은 경우에는 리스트를 사용해왔다. 하지만 현재는 생각이 바뀌게 되었다. Array(배열) vs ArrayList(리스트) In Java Array와 ArrayList의 차이점을 간단하게 정리해보자. Array(배열) 사이즈가 정적인 데이터 구조 primitive 타입과 인스턴스 타입 모두 원소로 포함될 수 있다. Generic(제너릭)을 사용할 수 없다. 부수적인 내용 (길이를 구할때는 length 변수를 사용, 할당은 = 를 사용, ...) ArrayList(리스트) 사이즈가 동적인 데이터 구조 인스턴스만 원소로 포함될 수 있다. Generic(제너릭)을 지원한다..

Language/Java 2022.09.07

Java - 리플렉션 사용하기!

리플렉션은 구체적인 클래스 타입을 알지 못해도, 해당 클래스의 메소드나 타입, 변수 들에 접근할 수 있도록 해주는 자바 API이다. 리플렉션은 JVM이 클래스 로더를 통해 읽어온 클래스 정보(reflect된 정보)를 통해 접근한다. 리플렉션은 아래의 경우 사용한다. 특정 애노테이션이 붙어있 필드 또는 메소드를 읽어오기 특정 이름 패턴에 해당하는 메소드 목록 가져와 호출하기 ... 예시 리플렉션을 사용하면 문자열로 클래스를 만들 수 있다. 아래의 코드를 보자. Class HelloClass = Class.forName("jaehoney.blogcode.Hello"); 문자열(package name)를 사용해서 클래스 정보를 꺼내온다. 이후에 해당 클래스의 인스턴스를 만들 수도 있다. Constructor ..

Language/Java 2022.09.04

Effective Java - 추상 클래스와 인터페이스 차이

Java 8부터 인터페이스도 default method를 제공할 수 있게 되었다. 즉, 추상 클래스와 인터페이스 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다. Effective Java에서는 '가능한' 추상클래스가 아닌 인터페이스를 활용하는 것을 권장한다. 그 차이는 무엇인지 알아보자. Abstract Class vs Interface 해당 두 가지 개념의 가장 큰 차이는 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다는 점이다. 자바는 단일 상속만 지원하니, 추상 클래스 방식은 새로운 타입을 정의하는 데 커다란 제약을 안게 되는 것이다. 반면, 인터페이스를 구현하면 다른 어떤 클래스를 상속했든 같은 타입으로 취급된다. 기존 클래스에도 손쉽게 새로운 ..

Language/Java 2022.09.02

Effective Java - Comparable을 잘 구현하는 방법!

Comparable Java로 알고리즘 공부를 하는 사람이라면 Comparable을 매우 자주 사용하게 된다. Comparable을 구현하면 인스턴스들의 순서를 손쉽게 정할 수 있다. 문제는 Comparable을 구현하는 방법을 잊어먹는 경우가 많다. 이는 Comporable 구현이 어렵기 때문이다. 예시 일반적으로 Comparable을 사용하는 예시를 살펴보자. class Point implements Comparable { int x, y, z; @Override public int compareTo(Point p) { if(this.x > p.x) { return 1; } else if(this.x == p.x) { if(this.y > p.y) { return 1; } else if(this.y ..

Language/Java 2022.09.01