1. JUnit 5 테스트 인스턴스 테스트 클래스에 있는 각각의 테스트 메서드는 서로 다른 인스턴스에서 실행됩니다. 다음 코드를 살펴보겠습니다. class MyTest { int value = 0; @Test void first() { System.out.println(value++); } @Test void second() { System.out.println(value++); } } 위 MyTest 클래스를 전체 테스트해보면 second()에서는 1이 찍혀야할거 같지만, 콘솔에 모두 0이 찍힙니다. 테스트 메서드는 서로 독립적이여야 한다는 특징때문에 각 테스트 메서드를 실행하는 인스턴스를 할당하는 것 같습니다. 만약, 하나의 인스턴스에서 실행되도록 만들고 싶다면 @TestInstance 를 사용하면 ..
1. 개요 변환에는 크게 두 가지 종류가 있습니다. 자료구조의 변환. 예를 들어, List를 Integer[]로의 변환. (타입은 유지되고 자료구조만 변환하고 싶은 경우) 자료형의 변환. 예를 들어, int 타입을 Integer 타입으로 변환하고 싶은 경우 해당 포스팅은 자료형을 변환시키고자 하는 것으로 위에서 두 번째 경우에 해당합니다. 그럼 어떤 경우에 자료형을 변환해야할까요? 🤔 int[] 배열을 오름차순 정렬하고싶다면 Arrays.sort()로 간단히 해결할 수 있습니다. 하지만, 내림차순 정렬을 하고싶다면 두 번째 파라미터로 Comparator를 정의해줘야하는데, 이때 value타입은 불가능합니다. 2. Integer[] ---> int[] 로의 변환 Java8의 람다와 스트림을 활용하는 방법으..
정규 표현식은 예시로 살펴보는게 가장 좋은 학습 방법인 것 같다. String#replaceAll 메서드를 이용한 정규 표현식 예 첫 번째 요구사항 --- 전체 URL에서 도메인의 정보만 뽑아내고 싶다. @Test public void 정규_표현식_테스트() { String str = "https://pangtrue.tistory.com/post/100"; str = str.replaceAll("(?i:https?://([^/]+)/.*)", "$1"); assertEquals(str, "pangtrue.tistory.com"); } 위 regexp를 분석해보자. 먼저, regexp에는 non-capturing group과 capturing group 두 가지의 그룹 방식이 있다. (?:) ---> no..
생성자나 정적 팩터리 메서드 둘 다 선택적 파라미터가 많은 경우에 문제가 있다. 1. 점층적 생성자 패턴 영양 성분표를 나타내는 클래스를 예로 들어보자. public class NutritionFacts { private final int servingSize; // 필수로 입력되어야하는 파라미터 private final int servings; // 필수 private final int calories; // 선택 private final int fat; // 선택 private final int protein; // 선택 private final int carbohydrate // 선택 public NutritionFacts(int servingSize, int servings) { this(serv..
클래스를 통해 객체를 만드는 방법은 세 가지가 있다. public으로 선언된 생성자 정적 팩터리 메서드 빌더 패턴 위의 세 가지 방법 중 가장 일반적인 것은 첫 번째 방법인데, 이 대신에 정적 팩터리 메서드를 사용할 수는 없는지 고려해보자. 정적 팩터리 메서드를 이용해 객체를 만드는 하나의 예시는 아래와 같다. public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 1. 생성자 대신 정적 팩터리 메서드를 사용할 때의 장점 첫 번째, 생성자와는 달리 정적 팩터리 메서드에는 이름이 있다. 예를 들어, 소수일 가능성이 높은 BigInteger 객체를 생성하는 생성자 BigInteger(int, int, Rando..
Map을 순회하는 방법을 정리해보겠습니다. 첫 번째, Iterator를 통해 접근하기 Map map = new HashMap(); Iterator keys = map.keySet().iterator(); while (keys.hasNext()) { String key = keys.next(); map.get(key); } 두 번째, entrySet으로 접근하기. Map은 하나의 원소로 Key-Value 묶음을 가지기 때문에 원소란 표현 대신 Entry라고 표현합니다. Map map = new HashMap(); for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); } 세 번째..
웹 애플리케이션을 유지보수하거나 추가 개발하는 과정에서 특정 라이브러리의 기능을 테스트해보고 싶은 경우가 많이 있다. 나 같은 경우 간단하게 StringUtils의 메서드 결과 값이 어떻게 나오는지 테스트해보고 싶었는데, 이런 간단한 작업을 하기 위해 메인 소스 영역에 아래와 같은 코드를 넣은 후, 웹 애플리케이션을 구동하는걸 반복하다보니 이건 아니다 싶었다.. int idx = StringUtils.indexOf("abcdefg_1234", '_'); log.info("result : ", idx); 반면에 src/test/java 영역에 해당 코드를 작성하면 결과 값을 가볍게 바로 확인할 수 있다. public class StringUtilsTest { @Test public void test() {..
Nexus란? Nexus는 사설 Maven 저장소로 사용이 가능한 가장 널리 사용되는 무료 repository이다. 당연히, 로컬에 Nexus를 설치하게되면 외부의 저장소에서 dependency를 가져오지않아도 된다. 현재 다니고있는 회사가 Nexus를 이용해서 사설 Maven 저장소를 구축해놓았고, 사내에서 사용될 프레임워크 및 라이브러리를 해당 저장소에 놔두고 사용 중이다. 사설 Nexus 저장소를 구축했을 때의 특징 로컬에 Nexus를 구축하면 이를 프록시로 사용함으로써 빠르게 라이브러리들을 가져올 수 있다. 개발팀 내에서 사용하는 공통 라이브러리들을 사설 Nexus에 배포해서 팀간에 공유할 수 있다. build.gradle에 아래의 코드처럼 Maven 저장소를 설정해줄 수 있다. buildscri..
1. XML 파싱 JSON이 편리하고 많이 사용되는게 사실이지만, XML 또한 많이 사용되는 것도 사실입니다. 그렇기 때문에, 데이터를 XML로 만드는 것과 XML을 파싱해서 데이터를 이용하는 것 둘 다 할 줄 알아야합니다. XML 파싱이라는 작업이 워낙에 일반적이다보니 Java는 XML 파서를 내장하고 있습니다. 2. 내장 라이브러리를 사용한 XML 파싱 예제 아래와 같은 구조의 XML 파일이 있다고하겠습니다. Alsa 25 Bob 28
1. JVM이란? C 프로그램의 실행 프로세스를 한 번 생각해보자. preprocessor를 거쳐 코드가 확장된다. 확장된 코드는 compiler를 통해 어셈블리 코드로 변환된다. 변환된 어셈블리 코드는 assembler를 통해 바이트 코드를 가진 .obj 파일로 변환된다. .obj 파일은 linker를 통해 외부의 라이브러리 코드와 연결시킨 후, 실행 파일(.exe 등)을 생성한다. 실행이 가능해진 코드는 loader를 통해 메모리에 로드되고, 기계는 이를 해석하며 그에 따라 동작한다. C 프로그램은 위와 같은 프로세스를 머신에서 수행하고, Java는 가상머신을 이용해 이와 같은 프로세스를 처리한다. JVM이 하는 일은 크게 3가지 코드를 로드하고, 검증하고, 실행한다. OS로부터 메모리를 할당받아 관..
try-with-resources는 try(...)문 안에서 선언된 객체에 대해서 try가 종료될 때 자동으로 자원을 해제( close() 메서드 호출 )해주는 기능이다. 단, try( ... ) 문 안에 선언된 객체가 AutoClosable 인터페이스를 구현한 객체여야한다. public interface AutoCloseable { void close() throws Exception; }
java.nio 패키지 참고로 nio는 New I/O의 약자. ( non-blocking의 약자인줄 알았는데 아님. ) 기존의 java.io 패키지를 대체하기 위해 새롭게 나온 패키지다. 과거 Java I/O는 C/C++과 비교해 매우 많이 느리다는 평가가 많았는데, 이유는 두 가지다. 커널 버퍼를 직접적으로 핸들링할 수 없다. blocking I/O다. 기존의 io 패키지에서는 데이터가 흘러가는 통로를 stream이라는 용어를 써서 표현했고, 새로운 nio 패키지에서는 데이터가 흘러가는 통로를 channel이라는 용어를 써서 표현한다. Stream VS Channel Stream의 특징은 다음과 같다. 읽기/쓰기를 할때 InputStream과 OutputStream으로 구분해서 사용했다. ( 단방향 )..