Dev 226

[Effective JAVA] 생성자 대신 정적 팩터리 메서드를 고려하라. ( 아이템 1 )

클라이언트가 특정 클래스의 인스턴스를 얻으려면 new 연산자로 public 생성자를 호출하면 된다. 하지만 이는 많은 단점을 가지고 있다. 1) 생성자는 오버로딩되어 파라미터에 따라 다양한 형태가 존재하는데, 생성자는 모두 동일한 이름이라 어떤 생성자가 어떤 종류의 인스턴스를 생성하는지 알 수 없다. 2) new 연산을 할 때마다 객체가 하나씩 생성되므로, 호출이 잦은 객체인 경우 쓸데없이 많은 객체가 생성될 수 있다. 3) 자기 자신의 인스턴스만 생성 가능하다. 4) 클라이언트와 생성하려는 클래스의 생성자를 참조하가 위해 클래스를 import 해야하므로 결합도가 올라간다. 이는 정적 팩터리 메서드로 해결 가능하다. 1) 생성자는 오버로딩되어 파라미터에 따라 다양한 형태가 존재하는데, 생성자는 모두 동일..

Dev/JAVA 2024.03.20

[ModernJAVA] Stream이 필요한 이유

컬렉션(Collection)은 데이터를 그룹화시켜 처리할 수 있도록 도와주는 자료구조이다. JAVA는 자료구조에 저장된 데이터를 조작할 수 있도록 Collection 인터페이스를 제공한다. 그러나 문제가 있다. 멀티코어 환경이 대중화 되면서 병렬 프로세스가 중요해졌다. 컬렉션에 저장된 데이터를 여러 스레드에 분산처리하면 높은 성능을 낼 수 있기 때문이다. 그러나 그 과정을 코드로 구현하기란 여간 복잡한 것이 아니다. JAVA는 명령형 프로그래밍이기에, 과정을 하나하나 코드로 구현해야만 한다. 음식 컬렉션을 세 가지 과정을 거쳐 조작해보자. 1) 400 칼로리 이하인 음식으로 필터링 한다. 2) 칼로리가 낮은 순으로 정렬한다. 3) 음식의 이름만 추출한다. 세 가지 과정을 명령형 프로그래밍으로 개발하면 아..

Dev/JAVA 2024.03.05

[JAVA] String, StringBuffer, StringBuilder의 차이

String, StringBuffer, StringBuilder의 차이를 정리하면 아래와 같다. String은 불변객체이고 StringBuffer, StringBuilder는 가변객체이다. StringBuffer는 멀티스레드 환경에서 사용되고 StringBuilder는 싱글스레드 환경에서 사용된다. 왜 이런 차이를 보이는 것일까? String이 불변객체인 이유 String이 불변객체인 이유는 JAVA가 문자열 리터럴을 String Constant Pool로 관리하기 때문이다. "안녕하세요", "반갑습니다.", "hello" 처럼 선언된 문자열은 문자열 리터럴로 간주되어 Heap 메모리 안에 생성된 String Constant Pool에 문자열 객체로 등록된다. 스레드A가 "안녕하세요" 문자열 객체를 리터..

Dev/JAVA 2024.02.23

[JAVA] Garbage Collector 동작원리

JAVA와 C, C++의 가장 큰 차이 중 하나는 가비지 컬렉터(Garbage Collector) 이다. JVM의 스레드는 Stack 영역에 독립된 공간을 가지고 Heap 영역은 공유한다. 그래서 가비지 컬렉터 스레드가 Heap 영역의 생성된 객체에 접근하여 제거할 수 있다. 이런 구조는 C/C++도 마찬가지이지만, C/C++은 가비지 컬렉터를 가지고 있지 않다. 왜냐하면 가비지 컬렉터는 치명적인 단점을 가지고 있기 때문이다. 가비지 컬렉터는 Mark-Sweep-Compaction 과정을 거쳐 객체를 제거한다. Mark 전역 메모리 영역, 스택 영역의 참조변수에서 접근할 수 있는 객체는 reachable, 접근할 수 없는 객체는 unreachable로 표시(Mark)한다. Sweep unreachable..

Dev/JAVA 2024.02.23

[JAVA] JDK 동작원리

JDK( Java Develoment Kit ) JDK는 자바 컴파일 도구(javac) , 자바 실행 환경 ( JRE ) , 자바 실행 머신 ( JVM )이 합쳐진 도구이다. JAVA 언어로 개발하려면 JDK가 필요하지만 단순히 실행만 한다면 JRE만 있어도 된다. 그럼 이제 JDK는 어떻게 동작하는지 구체적으로 알아보자. 객체지향언어, JAVA C,C++은 절차지향언어지만 JAVA는 객체지향언어이다. 절차지향언어는 코드의 '순서'가 중요하므로 코드 전체가 유기적으로 연결되어 있다. 그래서 메모리에 올라갔을 때의 주소도 논리적으로 이미 정해져 있다. 이를 '정적바인딩'이라 부른다. C,C++은 컴파일(compile)을 하면 컴퓨터가 이해할 수 있는 언어인 어셈블리어로 바로 변환된다. 이미 메모리 위치까지..

Dev/JAVA 2024.02.22

[Spring] Bean 생명주기 콜백 ( @PostConstruct, @PreDestory )

Bean은 [ 객체 생성 -> 의존관계 주입 -> 스프링 컨테이너 상주 -> 소멸 ] 의 과정을 거친다. Bean은 스프링이 대신 생성해주므로, 초기화 작업과 종료 작업이 원할히 진행 될 수 있도록, 스프링은 의존관계 주입 된 이후와 소멸되기 직전에 개발자가 특정한 로직을 수행시킬 수 있도록 '콜백(CallBack)'을 제공한다. 초기화 작업은 생성자 로직에 포함시킬 수는 있지만 초기화 과정이 무거운 경우, 객체 생성과 초기화 작업을 분리하는 것이 좋다. 이 경우, Spring이 제공하는 초기화 콜백을 사용하는 것이 좋다. 콜백을 제공하는 방식은 3가지가 있다. 1) InitializingBean, DisposableBean 인터페이스 2) @Bean(initMethod = "init", destroyM..

Dev/SPRING 2024.02.06

[Spring] Bean 자동등록 VS Bean 수동등록

어노테이션으로 스프링 컨테이너에 Bean을 등록하는 방법은 2가지가 있다. 1) 컴포넌트 스캔으로 자동등록 ( @Component, @Service, @Repository ... ) 2) @Configuration 클래스에 수동등록 ( @Bean ) 두 가지 방식은 언제 어떻게 사용하는 것이 좋을까? 1) 업무로직 VS 기술지원 자동방식은 컴포넌트 스캔으로 @Component로 선언된 클래스를 자동으로 Bean으로 등록하니 편하다. 그러나 @Component가 여기저기 퍼져 있어 추적이 힘들다. 수동방식은 @Configuration 클래스를 생성하고 Bean을 하나하나 정의해야 하는 번거로움이 있지만 하나의 클래스에 Bean이 모여 있다보니 관리가 쉽다. 그러므로 자동등록 방식은 업무로직 Bean에 사용..

Dev/SPRING 2024.02.06

[Spring] 스프링 컨테이너와 싱글톤 패턴

싱글톤 패턴 가장 단순한 방식으로 싱글톤 패턴이 적용된 클래스는 다음과 같다. 1. Static 영역에 상수로 인스턴스가 생성되어야 한다. 2. 생성자는 private 접근자로 막아놓는다. 3. 인스턴스는 static 메소드로만 외부 접근을 허용한다. public class Box { // 1. statice 영역에 상수로 객체를 생성한다. private static final Box instance = new Box(); // 2. 생성자는 private 접근자로 막아놓는다. private Box(){ } // 3. 인스턴스는 static 메소드로 조회한다. public static Box getBox(){ return instance; } } 웹에서 싱글톤 객체가 중요한 이유는 수많은 Request가..

Dev/SPRING 2024.02.05

[Spring] 스프링을 사용하는 이유

스프링(Spring)을 사용하는 이유 스프링을 사용하는 이유는 객체(Bean) 생성과 의존관계 주입(DI)을 대신 해주기 때문이다. ( IOC, 제어의 역전 ) 그렇다면, 개발에서 객체생성과 의존관계 주입을 대신 해주는 프레임워크가 필요한 이유는 무엇일까? Spring은 객체지향개발을 도와주는 프레임워크이다. 객체지향개발에서 핵심은 객체 간 결합도를 줄이는 것이다. public class Computer { MouseA mouseA = new MouseA(); // MouseA에 의존, 결합도 증가 public void click(){ mouseA.click(); // MouseA에 의존 } } 컴퓨터 객체가 마우스 객체를 참조하면 클릭 기능을 사용할 수 있다. 그러나 위 코드와 같이, 컴퓨터가 특정 마..

Dev/SPRING 2024.02.01

[Modern JAVA] 클로저(Closure)란?

JAVA에서 클로저(Closure)란? 클로저(Closure)란, 외부 스코프에 선언된 변수를 다른 스코프 영역에서 참조하는 기술이다. 사실, JAVA에서 클로저는 없는 개념이다. 익명함수 클래스나 람다로 인스턴스를 생성할 때, 외부 스코프 변수를 캡처하여 인스턴스 내부에 저장하는 '캡처링' 기술을 두고, 단순히 클로저라 부르는 것이다. 외부에 선언된 변수를 내부에서 사용하니, 마치 클로저 같은 기능을 하기에 붙여진 이름이다. 외부 변수를 캡처하여 인스턴스에 저장하면, 외부에 있는 데이터와 인스턴스에 저장된 데이터는 서로 동일해야 한다. 만약 둘 중 하나가 변경되면 데이터 멱등성이 훼손되기 때문이다. 그래서 JAVA8 이전에는 캡처링 기술이 적용될 변수는 변경되지 못하도록 final 선언을 강제했다. J..

Dev/JAVA 2024.01.31