LocalDate, LocalDateTime 변환

LocalDate → LocalDateTime 시간을 지정해줘야 되나는 문제가 있다. atStartOfDay() 메서드는 0시 0분 0초로 시간이 매핑된다. atTime()은 자신이 원하는 시간을 LocalTime 이나 (시, 분, 초) 형태로 파라미터를 입력할 수 있다. LocalDateTime localDateTime1 = localDate.atStartOfDay(); LocalDateTime localDateTime2 = localDate.atTime(LocalTime.now()); LocalDateTime localDateTime3 = localDate.atTime(04, 30, 56); LocalDateTime → LocalDate LocalDate localDate = localDateTime.toLocalDate(); 참고 자료 https://howtodoinjava.com/java/date-time/localdate-localdatetime-conversions/

2024-09-15 · 1 min · 53 words

Kotlin과 Java 혼용시 Checked Exception 알려주기

상황 코틀린에서는 Checked Exception을 따로 처리해주지 않는다. 자바에서 Checked Exception을 catch 해서 처리해주고 싶은데 이가 문제가 되었다. 해결 방법 코틀린에 @Throws 어노테이션을 사용하면 자바에서 checked exception 처리가 가능해진다. @Throws(IOException::class) fun foo() { throw IOException() } 참고 자료 https://kotlinlang.org/docs/java-to-kotlin-interop.html#checked-exceptions https://stackoverflow.com/questions/36528515/throws-exception-in-a-method-with-kotlin

2024-09-15 · 1 min · 39 words

JDK 라이센스 문제

Java 애플리케이션을 컴파일하기 위한 JDK는 크게 Oracle JDK와 OpenJDK로 나뉜다. Oracle JDK의 경우 일반적인 목적(General Purpose Computing)이 아닌 경우 라이센스 비를 지불해야된다. 따라서, 여러 회사에서는 이 애매한 표현 때문에 대부분 오픈소스인 OpenJDK를 사용한다. Java SE7부터 모든 JDK는 OpenJDK 레퍼런스 코드를 기반으로 제작된다. Oracle JDK 또한 마찬가지다. OpenJDK 운영 주체 또한 Oracle이다. 오라클이 아닌 서드파티 업체가 OpenJDK를 기반으로 공인된 JDK를 제작하여 배포하려면 오라클의 유료 라이센스인 OCTLA에 가입해야 한다. 현재 전세계에 19개 업체가 가입되어 있다....

2024-09-15 · 1 min · 103 words

JDBC의 SQL Injection 대응

정확히는 JDBC 내부적으로 SQL Injection에 대응하고 있다. PreparedStatement 클래스를 예로 들면 setString() 메서드에 내부적으로 SQL Injection에 대응하고 있기 때문에 안전하게 사용할 수 있다. https://www.baeldung.com/sql-injection 따라서 아래와 같은 코드를 작성하지 않도록 조심하자. String sql = "select " + "customer_id,acc_number,branch_id,balance " + "from Accounts where customer_id = '" + customerId + "'"; Connection c = dataSource.getConnection(); ResultSet rs = c.createStatement().executeQuery(sql); select count(1) from user where id = ? and password = ?

2024-09-15 · 1 min · 70 words

JDBC에서 모든 테이블 이름 찾기

Rest Assured를 통한 E2E 테스트 진행시, 모든 테스트를 독립적으로 만들기 위해 각 테스트마다 모든 테이블을 TRUNCATE 할 필요가 있었다. 그래서 모든 테이블의 이름을 찾는 과정이 필요했다. DatabaseMetaData 를 통해 찾을 수 있다고 한다. DatabaseMetaData는 Connection을 통해 얻을 수 있다. 나같은 경우 Spring을 사용하고 있어서 JdbcTemplate를 통해서 구할 수 있었다. private void truncateAllTables() throws SQLException { JdbcTestUtils.deleteFromTables(jdbcTemplate, getAllTables().toArray(new String[0])); } private List<String> getAllTables() throws SQLException { DatabaseMetaData metaData = jdbcTemplate.getDataSource().getConnection().getMetaData(); List<String> tables = new ArrayList<>(); try (ResultSet resultSet = metaData....

2024-09-15 · 1 min · 104 words

JDBC에서 MySQL의 COUNT 함수 리턴 타입

배경 MyBatis를 이용해 특정 id별 COUNT 결과를 Pair<Long, Int> 로 리턴했더니, 타입 캐스팅 예외가 발생했다. java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer 문제 상황 예시 코드 @Select("...") fun countByIds(ids: List<Long>): List<Pair<Long, Int>> 원인 MySQL의 COUNT 함수의 리턴 타입은 BIGINT 이다. MySQL JDBC Driver 에서 BIGINT는 기본적으로 Java의 Long 타입으로 변환되므로 타입 캐스팅 예외가 발생한다. 참고 자료 https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count https://dev.mysql.com/doc/connector-j/en/connector-j-reference-type-conversions.html

2024-09-15 · 1 min · 58 words

JDBC execute vs executeQuery vs executeUpdate

execute: 일반적인 sql 실행. 리턴 타입이 ResultSet이면 TRUE, 아니면 false다. executeQuery: 특정 데이터를 탐색할 때 사용하는 메소드. 리턴타입이 ResultSet이다. executeUpdate: DML, DDL 등을 입려할 때 사용하는 메소드. 리턴타입이 int로 영향받은 행의 개수를 반환한다. 참고 자료 https://javaconceptoftheday.com/difference-between-executequery-executeupdate-execute-in-jdbc/

2024-09-15 · 1 min · 36 words

Java의 Comparator와 Comparable

Java에서 커스텀 클래스를 PriorityQueue에 담기 위해서, 정렬 기준을 구현할 필요가 있다. Java에서 정렬을 구현하는 방법에는 두 가지가 있다. Comparable 인터페이스 구현 Comparator 인터페이스 구현 위 두 인턴페이스 모두 함수형 인터페이스로 람다식으로 표현도 가능하다. Comparable 하나의 객체가 다른 객체를 비교할 수 있음을 나타내는 인터페이스다. public int compareTo(T o) 메서드를 구현하면 된다. 정렬 순서를 정할 때, 비교할 대상의 객체보다 앞에 오게 하려면 음수를 반환, 뒤에 오게 하려면 양수를 반환, 같으면 0을 반환하면 된다....

2024-09-15 · 2 min · 254 words

Java에서 String이 불변 객체인 이유

Java에서 String a, b 를 더했을 때 나오는 결과는 새로운 주소값을 가지는 것을 확인할 수 있다. 이렇게 Java에서는 왜 String을 불변 객체로 관리가 되는지 정리해본다. 1. String Pool로 인한 메모리 절약 Java에서는 String 리터럴 값을 사용하면 String Pool에 값을 캐싱하게 된다. 같은 String이라면 새로 인스턴스를 생성하지 않고 String Pool에서 재사용하기 때문에 힙 메모리 영역을 절약할 수 있다. 2. 보안 String은 사용자 이름, 비밀번호 등 민감한 정보를 저장하기 위해 주로 사용된다. 만약 String이 불변이 아니라면, 문자열을 사용하는 중간에 값이 바뀔 수도 있어서 안전하지 않다....

2024-09-15 · 1 min · 148 words

Java 스레드

기본 소개 Java에서는 경합 상태일 때 데이터의 정합성을 보장하기 위해 스레드 동기화로 한 번에 하나의 스레드만 공유 자원에 접근할 수 있도록 한다. 이를 구현하기위해 Java에서는 각 인스턴스들이 자신의 Monitor를 가지게하고, 스레드가 이 인스턴스를 사용할 때 Monitor를 점유하도록 한다. 이 Monitor는 하나의 스레드만 점유할 수 있기때문에, 다른 스레드들은 Wait Queue에서 기다리게 된다. (synchronized 키워드를 사용하면 점유하게된다) Java 스레드에는 ‘데몬 스레드(daemon thread)’와 ‘일반 스레드(non-daemon thread)’가 있다. 데몬 스레드: 백그라운드로 실행되고, 일반 스레드가 모두 종료되면 데몬 스레드의 의미가 사라지기 때문에 강제적으로 자동 종료된다....

2024-09-15 · 2 min · 249 words

Java 메서드 파라미터의 final 자동으로 붙이기

2024-09-15 · 0 min · 0 words

IP 형태의 문자열인지 확인하는 방법

Guava 라이브러리를 사용했다. // an IPv4 address private static final String INET4ADDRESS = "172.8.9.28"; // an IPv6 address private static final String INET6ADDRESS = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; // Validate an IPv4 address if (InetAddresses.isInetAddress(INET4ADDRESS)) { System.out.print("The IP address " + INET4ADDRESS + " is valid"); } else { System.out.print("The IP address " + INET4ADDRESS + " isn't valid"); } // Validate an IPv6 address if (InetAddresses.isInetAddress(INET6ADDRESS)) { System.out.print("The IP address " + INET6ADDRESS + " is valid"); } else { System....

2024-09-15 · 1 min · 89 words

InputStreamReader의 close

InputStream을 character stream으로 사용할 수 있게해주는 InputStreamReader는 close를 하게되면 내부에 가지고 있는 InputStream도 함께 close되기 때문에 주의해서 사용해야된다. https://stackoverflow.com/questions/55549248/do-i-need-to-close-inputstreamreader-even-if-inputstream-should-remain-open

2024-09-15 · 1 min · 19 words

Inner class와 Static inner class의 차이

public class Test { class InnerClass { // InnerClass } static class InnerStaticClass { // static InnerClass } } Inner class는 외부 클래스를 인스턴스화해야지 inner class도 인스턴스화가 가능하다. 하지만 static은 외부 클래스 인스턴스화 필요없이도 인스턴스화가 가능하다. static이라고해서 InnerStaticClass 인스턴스가 하나만 존재하는 것이 아니니 유의해야된다. https://velog.io/@agugu95/왜-Inner-class에-Static을-붙이는거지

2024-09-15 · 1 min · 45 words

HttpServletResopnse에 string 출력하기

response.setContentType("text/html; charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); getOutputStream 의 경우는 바이트 기반 스트림이기 때문에 utf-8로 제대로 인코딩하지 못하는 문제가 있다. https://stackoverflow.com/questions/1992400/how-to-send-through-servletoutputstream-characters-in-utf-8-encoding

2024-09-15 · 1 min · 21 words

getDeclaredMethods() 와 getMethods() 차이

getDeclaredMethods()는 해당 클래스로부터 직접 정의한 모든 메소드(protected, private 포함)를 반환된다. 하지만 getMethods()는 public 메소드만 반환하지만 부모 클래스로부터 정의된 메소드도 함께 반환된다. https://stackoverflow.com/questions/43585019/java-reflection-difference-between-getmethods-and-getdeclaredmethods

2024-09-15 · 1 min · 22 words

File 경로 찾기

String resourceName = "example_resource.txt"; ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource(resourceName).getFile()); String absolutePath = file.getAbsolutePath(); System.out.println(absolutePath); assertTrue(absolutePath.endsWith("/example_resource.txt")); ClassLoader를 사용하면 classpath에서 해당 파일의 위치를 찾는다. 서브 디렉토리까지 찾지 않는 점의 유의해야된다. 참고 자료 https://www.baeldung.com/junit-src-test-resources-directory-path

2024-09-15 · 1 min · 35 words

ExecutorService 이해하기

목표 ExecutorService의 역할을 이해한다. ExecutorService의 대표적인 메서드를 이해한다. Runnable 스레드에 의해 실행될 작업을 나타내는 함수형 인터페이스 void run() 메서드를 가지고 있다. Executor Runnable 작업을 실행시켜주는 인터페이스 실행 작업과 각 작업이 실행되는 메커니즘(스레드 사용, 스케쥴링 등)을 decoupling 시켜주는 인터페이스이다. 일반적으로 executor에서 실행되는 작업은 다른 스레드에서 실행된다. class ThreadPerTaskExecutor implements Executor { public void execute(Runnable r) { new Thread(r).start(); } } 하지만 Executor의 구현체가 항상 비동기나 다른 스레드로 실행되어야 한다는 제한은 없다. class DirectExecutor implements Executor { public void execute(Runnable r) { r....

2024-09-15 · 2 min · 355 words

EnumSet

목표 EnumSet 의 정의 EnumSet의 장단점 EnumSet 정의 enum 클래스에서만 사용할 수 있는 Set 이다. null 값을 추가하면 NPE가 발생한다. 스레드로부터 안전하지 않다. 내부 구현 비트 벡터를 사용해서 각 enum의 포함 여부를 저장한다. EnumSet.of() 등을 통해서 생성하면, enum 값의 개수에 따라 두 가지 구현이 존재한다. RegularEnumSet: long 타입을 통해서 저장하며, long은 64비트 타입이므로 64종류를 저장할 수 있다. JumboEnumSet: long의 배열을 통해서 저장하며, 64개 이상의 종류를 저장할 수 있다. 장단점 장점 모든 연산이 비트 연산을 사용하기 때문에 처리 속도가 빠르다....

2024-09-15 · 1 min · 132 words

CountDownLatch

목표 CountDownLatch가 무엇인지 이해한다. CountDonwLatch 다른 스레드가 주어진 작업을 완료할 때까지 현재 스레드를 블락하기 위해서 사용할 수 있다. counter 필드를 가지고 있고, 상황에 따라 이를 감소시킬 수 있다. counter 필드가 0이 될 때까지, 호출한 스레드에서는 블락된다. 예제 코드 테스트 코드에서는 assertThat을 호출하기 전에 5개의 Worker 가 모두 동작이 끝나기를 기다려야된다. 테스트 코드에서 CountDownLatch(5)로 선언하고, 각 Worker에서 1씩 감소시키는 방식으로 대기를 시킨다. public class Worker implements Runnable { private List<String> outputScraper; private CountDownLatch countDownLatch; public Worker(List<String> outputScraper, CountDownLatch countDownLatch) { this....

2024-09-15 · 1 min · 194 words