I. Index
1. Optional 자료형
2. 동시성 문제
3. stream
4. Assertions (assertThat, ifPresent)
5. IllegalStateException
II. Contents
1. Optional 자료형
What (정의) : Nullable한 값을 감싸는 래퍼클래스이다. 명시적으로 값이 없는 경우와 다를 수있으며, NullPointerException을 방지할수있음
Why (존재이유) :
Null 안전성 향상 Null안전성 강화하기 위해서이다. NPS상황을 방지하고, 코드안전성을 향상시킴
가독성 향상 null체크와 관련된 복잡한 로직을 줄여줌
명시성 강화 값이 없을 경우에 대한 명시성을 코드에 반영이 가능함
예
//repository 에서...
@Override
public Optional<Member> findById(Long id) {
//옵셔널로 감싸면 null인것을 방지할 수 있음
return Optional.ofNullable(stroe.get(id));
}
How (방법) :
// 값을 갖는 Optional 생성
Optional<String> optionalValue = Optional.of("Hello");
// 값이 없는 Optional 생성
Optional<String> emptyOptional = Optional.empty();
// 값이 없는 경우에 대한 Optional 생성
Optional<String> optionalNullable = Optional.ofNullable(null);
// 값 가져오기 (값이 없으면 NoSuchElementException 발생)
String value = optionalValue.get();
// 값 가져오기 (값이 없으면 디폴트 값 사용)
String valueOrDefault = optionalValue.orElse("Default Value");
// 값 가져오기 (값이 없으면 Supplier를 통해 생성)
String valueOrGenerated = optionalValue.orElseGet(() -> generateValue());
// 값 가져오기 (값이 없으면 예외 던지기)
String valueOrThrow = optionalValue.orElseThrow(() -> new RuntimeException("Value not found"));
// 값 존재 여부 확인
boolean isPresent = optionalValue.isPresent();
// 값이 존재할 때 처리
optionalValue.ifPresent(val -> System.out.println("Value: " + val));
// 값 변환 및 처리 (매핑)
Optional<Integer> lengthOptional = optionalValue.map(String::length);
public static void main(String[] args) {
System.out.println("Hello world!");
String a = "hi";
String b = null;
Optional<String> strOp = Optional.of(a);
Optional<String> nulOp = Optional.ofNullable(b);
System.out.println(strOp.get());
System.out.println(nulOp.orElse("null 임 "));
System.out.println(nulOp.isPresent());
// strOp.orElseGet(() -> generateValue());
// strOp.orElseThrow(() -> new ("not found"));
strOp.ifPresent(val -> System.out.println("value"+val));
}
e.g. (예) :
마치 선물상자와 마찬가지이다. 선물상자안에 선물이 '무엇'이 들어있는지는 모르지만 '있는지 없는지'(상자를 흔들어서,상자의 무게로)는 미리 확인이 가능하다.
2. 동시성 문제 (가볍게)
What (정의) : 멀티스레드 환경에서 동시에 공유된 자원을 접근, 수정하는 과정에서 발생하는 문제 이로인한 데이터 일관성 문제 발생
Why (존재이유) : 스프링 어플리케이션은 싱글톤 빈을 사용하는 상황에서 여러 스레드가 동시에 실행될 수있는 환경에서 동작한다. 각 스레드가 공유 데이터 자원을 접근 수정할 수있기 때문이다.
How (방법) : 해결방법으로는
Synchronized 로 하나의 스레드만 실행시키기,
Locking Mechanism 스레드간 경합조건을 제어하고 데이터 일관성 유지함,
Thread-Safe 컬렉션 및 객체 사용 스프링이 제공하는 것으로서 스레드를 안전하게 사용할 수있는 컬렉션, 객체를 제공함
Spring의 Transactional 스프링의 트랜잭션 관리기능을 사용하여 DB작업등을 원자적으로 처리하고, 데이터 일관성 보장 함
e.g. (예) :
하나의 은행계좌에 여러명이 동시에 입출금 시도하는 상황으로 볼 수있음
3. stream (가볍게)
What (정의) : 자바8에서 제공되는 기능이다. 데이터의 '연속된 흐름'을 나타낸다. 결국 컬렉션, 배열같은 데이터 구조에서 이를 이용할 수있다.
Why (존재이유) :
간결하고 가독성 있는 코드: 간결한 코드로 데이터 처리가 가능하다
병렬 처리의 용이성: 데이터를 병렬로 처리하는거이 간단해진다.
함수형 프로그래밍의 지원: 함수형 프로그래밍 개념 지원하기 때문에 불변성, 순수함수 활용이 가능하다
How (방법) :
3단계 (데이터소스 생성 -> 중개 연산 수행 -> 종단 연산 수행)
데이터 소스생성 : 다양한 데이터 소스로 부터 스트림을 생성한다
중개 연산 수행 : 스트림에 필터링, 매핑, 정렬을 수행한다.
종단 연산 수행: 마무리 후 결과 반환한다. 스트림을 닫으면 더이상 사용할수 없음
e.g. (비유) :
카페에서 커피를 주문할 때 메뉴, 사이즈, 원두종류 등을 선택하는것은 중개연산을 의미한다.
이를통해서 커피를 필터링하거나, 변형할수 있다.
그리고 주문이 완료되면 더이상 주문을 받을 수없다.
public static void main(String[] args) {
List<String> frus = Arrays.asList("사과", "바나나", "포도", "오렌지", "키위");
List<String> 필터과일 = frus.stream()
.filter(fru -> fru.length() >= 3)
//람다식 방식으로 이렇게도 가능함
//.map(fruit -> fruit.toUpperCase())
//메소드 참조 방식 (String클래스에 정의된 정적 메소드임)
.map(String::toUpperCase)
//스트림을 이용해서 요소들의 컬렉션으로 수집하는 작업임
//즉 스트림 -> 리스트
.collect(Collectors.toList());
//필터과일.forEach(fruit -> System.out.println(fruit)); //람다식 방식
필터과일.forEach(System.out::println);
}
이 외 알아두면 좋은 스트림 요소 처리 메소드
- map: 스트림의 각 요소를 변환하여 새로운 스트림을 생성합니다.
- filter: 주어진 조건에 맞는 요소만을 필터링하여 새로운 스트림을 생성합니다.
- collect: 스트림의 요소를 컬렉션으로 수집합니다 (예: 리스트, 세트, 맵 등).
- reduce: 스트림의 요소를 하나의 값으로 축소하는 작업을 수행합니다.
- sorted: 스트림의 요소를 정렬합니다.
- findFirst 및 findAny: 스트림에서 첫 번째 요소 또는 임의의 요소를 반환합니다.
- max 및 min: 스트림에서 최대값 또는 최소값을 찾아 반환합니다.
4. Assertions (assertThat, ifPresent)
What (정의) : 테스트코드에서 예상결과 실제결과를 비교하고 확인하는데 메소드 제공하는 유틸리티 클래스이다. 즉 값이나 조건이 예상과 실제가 일치하는지 보는것이다.
Why (존재이유) : 동작하지않는 코드를 발견하고, 수정하려면 테스트결과를 신뢰할 수있어야함 Assertions를 사용해서 확인함으로서 코드변경에 따른 영향을 추적할수있고, 예상대로 된다는것 확신가능함
How (방법) :
- assertEquals(expected, actual): 예상한 값과 실제 값이 같은지 확인합니다.
- assertTrue(condition): 주어진 조건이 true인지 확인합니다.
- assertFalse(condition): 주어진 조건이 false인지 확인합니다.
- assertNull(object): 주어진 객체가 null인지 확인합니다.
- assertNotNull(object): 주어진 객체가 null이 아닌지 확인합니다.
- assertSame(expected, actual): 두 객체가 같은 객체인지 확인합니다.
- assertNotSame(expected, actual): 두 객체가 다른 객체인지 확인합니다.
e.g. (예) :
5. IllegalStateException
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다");
});
}
findByName은 optional로 선언되어있음
null이 아닌 'm'값이 있는 경우 (즉 Present true인 경우) thorw를 던짐
여기서 IllegalStateException 는?
부적절한 인수를 메소드 건내서 호출되는경우를 의미한다.
'배움 __IL > TIL 2기' 카테고리의 다른 글
TIL : Extra-3(.class, stringBuilder) (0) | 2023.08.29 |
---|---|
TIL : Extra-2(enum, hashMap) (0) | 2023.08.26 |
NginX의 필요성과 속성 실습(설치부터 로드밸런싱 실습) (0) | 2023.08.13 |