전체 글 682

[Effective JAVA] 인스턴스화를 막으려거든 private 생성자를 사용하라. ( 아이템 4 )

정적 클래스나 정적메소드만 사용하는 클래스는 public 생성자를 두어 외부접근을 허용할 위험을 가질 필요가 없다. 생성자를 정의하지 않으면 컴파일러가 자동으로 기본생성자를 public으로 만들어준다. 그렇다고 추상클래스를 만들면 안된다. 추상클래스를 상속하는 하위 객체가 생성될 때 추상클래스의 인스턴스도 생성되기 때문이다. 그러므로 클래스의 인스턴스화를 막으려면 private으로 선언된 생성자를 두면 된다. private으로 선언하면 외부에서 접근이 불가능하고 상속도 되지 않는다. 하위 객체가 부모객체를 생성하지 못하기 때문이다.

Dev/JAVA 2024.03.20

[Effective JAVA] private 생성자나 열거타입으로 싱글턴임을 보증하라. ( 아이템 3 )

싱글턴 객체를 만드는 방식을 둘 중 하나이다. 1) 필드 멤버 모든 생성자를 private으로 감추어 객체 생성을 불가능하게 만들고, public static final로 선언된 멤버만 외부로 노출한다. 권한이 있는 클라이언트는 reflection으로 private 생성자를 호출하여 객체를 생성할 수 있으나, 두 번째 객체가 생성될 때 예외를 발생시키는 것으로 방지할 수 있다. 2) 정적 팩터리 private static final로 선언된 멤버변수에 객체를 생성하고 정적 메소드로만 해당 상수를 return하는 방식이다. 정적 팩터리 방식은 정적 메소드를 이용한 방식이다. 장점1) 싱글톤 객체는 final로 선언된 변수를 참조하므로, 동적으로 테스트가 쉽지 않다. 메소드 로직으로 스레드 종류에 따라 다른..

Dev/JAVA 2024.03.20

[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

[K8S] Kubernetes 동작원리

Docker는 컨테이너 기술의 혁명을 가져왔다.   [Docker] 컨테이너란 무엇일까?Docker 아이콘은 고래 하나가 여러 개의 컨테이너를 싣고 있는 모습이다. 여기서, 고래는 '컴퓨터'이고 컨테이너는 '격리된 프로세스'이다. 도커가 혁명적인 이유는 컨테이너라는 환경분리를 리눅lordofkangs.tistory.com  리눅스 기술( cgroups, namespace)을 활용하여 리소스를 독립적으로 격리하고 할당이 가능해지자, 컨테이너(Container)라는 개념이 등장하였다. 하나의 컴퓨터 안의 여러 개의 컨테이너가 만들어졌고 모두 독립적으로 활동하였다. 이렇게 되자, 수많은 컨테이너를 관리하는 기술이 필요해졌는데, 그것이 바로 쿠버네티스(Kubernetes)이다.  쿠버네티스는 여러 대의 컴퓨터(..

Ops/Kubernetes 2024.02.25

[Docker] 컨테이너란 무엇일까?

Docker 아이콘은 고래 하나가 여러 개의 컨테이너를 싣고 있는 모습이다. 여기서, 고래는 '컴퓨터'이고 컨테이너는 '격리된 프로세스'이다. 도커가 혁명적인 이유는 컨테이너라는 환경분리를 리눅스 기술로만 이루어 냈다는 점이다. 도커가 존재하기 전에는 VM ( VirtualMachine ) 기술을 활용하였다. VM은 Hypervisor를 활용하여, 물리적으로 한 대의 OS 위에 가상의 Guest OS 여러 대를 실행 및 관리하는 구조이다. 무거운 커널이 여러 대가 동작하니, 그 위에서 동작하는 APP의 성능은 당연히 떨어질 수 밖에 없다. 도커는 커널의 존재를 하나로 줄였다. 커널이 하나만 존재할 수 있는 이유는 namespace와 cgroups를 활용하여 리소스를 독립적으로 분리하였기 때문이다. nam..

Ops/Docker 2024.02.24

[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

[PS] BOJ12865 평범한 배낭 ( DP ) with JAVA

12865번: 평범한 배낭 첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000) www.acmicpc.net ◎ 문제풀이 무게 제한이 있는 배낭에 아이템을 넣는 경우, 가치의 최댓값을 구하는 문제이다. 2가지 경우를 생각할 수 있다. 1) 배낭에 넣는 경우 2) 배낭에 넣지 않은 경우 그래서 DFS로 2가지 경우를 완전 탐색해도 될거 같지만, DP로 문제를 풀어보겠다. 무게 제한이 7인 배낭에 아이템1( 무게 6 ), 아이템2( 무게 4) , 아이템3( 무게 3 ), 아이템4( 무게 5 )를 넣으려고 한다..

문제풀이 2024.02.23

[PS] BOJ1446 지름길 ( DP ) With JAVA

1446번: 지름길 첫째 줄에 지름길의 개수 N과 고속도로의 길이 D가 주어진다. N은 12 이하인 양의 정수이고, D는 10,000보다 작거나 같은 자연수이다. 다음 N개의 줄에 지름길의 시작 위치, 도착 위치, 지름길의 길이 www.acmicpc.net ◎ 문제풀이 DP 발상이 가능하면 쉽게 풀 수 있는 문제이다. 어느 한 지점에 도착할 수 있는 경우는 2가지이다. 1) 바로 옆에서 1 이동하는 경우 2) 지름길로 이동하는 경우 지름길로 이동하는 경우는 여러가지가 될 수 있다. 그러므로 여러 가지 경우 중에서 가장 최소인 비용을 기억(메모리제이션) 해놓고 다음 지점의 최소비용 구할 때 사용하면 된다. 0부터 목표지점 D까지 Bottom-Up 방식으로 1씩 dp 값을 구하는 방식으로 문제를 풀면 된다...

문제풀이 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