Search
Duplicate
📒

[Java Study] 02-5. 자바 정적 유틸리티 클래스

상태
완료
수업
Java Study
주제
4 more properties
참고

정적 유틸리티 클래스

NOTE
정적 유틸리티 클래스는 인스턴스를 생성하지 않고, 오직 정적 메서드와 정적 필드만을 포함하는 클래스이며, 관련된 유틸리티 함수들을 그룹화하여 재공합니다!
Static은 메소드 영역에 속한다. (GC가 관리하지 않음)
정적 유틸리티 클래스는 인스턴스화 되지 않으며, private 생성자를 가집니다.
대부분의 정적 유틸리티 클래스는 상태를 유지 않으며, 입력된 매개변수만으로 작업합니다.
단순 메소드만 가지고 있는 구조로 객체지향에 벗어난 개념이되어 좋지 않은 방식으로도 불린다.

정적 유틸리티 클래스의 객체지향 설계

NOTE
유틸리티 클래스들이 객체 지향 설계 원칙에 어긋날 수 있는 몇 가지 문제점을 가지고 있다!
유틸리티 클래스는 상태를 저장하지 않는 정적 메서드의 집합이기 때문에, 객체 지향 프로그래밍의 핵심 원칙중 하나인 상태와 행동을 하나의 단위로 묶는 것을 따르지 않습니다.
유틸리티 클래스는 확장될 수 없습니다. 즉 정적 메서드를 오버라이드하거나 수정할 방법이 없어 유연하지 못합니다.
유틸리티 클래스의 메서드들을 사용하는 코드는 해당 클래스에 강하게 결합됩니다. 이는 테스트와 유지보수를 어렵게 만들 수 있으며, 특히 테스트 시 유틸리티 클래스의 메서드를 모킹하기 어렵습니다.

권장사항

유틸리티 클래스를 사용할 때는 객체 지향 설계 원칙을 고려하고 필요한 경우에만 사용하는것이 좋습니다.
유틸리티 클래스를 사용해야 할 경우, 클래스가 단일 책임 원칙을 따르도록 하고 너무 많은 기능이나 책임을 하나의 유틸리티 클래스에 넣지 않도록 주의해야 합니다.
최신 자바 버전에서는 인터페이스 내에 정적 메서드와 디폴트 메서드를 정의할 수 있습니다.

java.util.Objects

NOTE
Objects는 객체에 대한 일반적인 연산을 수행하는 정적 메서드들을 제공해 다양한 연산을 쉽게 처리할 수 있게 도와주는 유틸리티 클래스입니다.
// requireNonNull 예제 try { Objects.requireNonNull(null, "객체가 null입니다."); } catch (NullPointerException e) { System.out.println(e.getMessage()); // "객체가 null입니다." } // isNull 및 nonNull 예제 String e = null; System.out.println(Objects.isNull(e)); // true System.out.println(Objects.nonNull(e)); // false // requireNonNullElse 예제 String str1 = null; String str2 = "기본 문자열"; System.out.println(Objects.requireNonNullElse(str1, str2)); // "기본 문자열" // requireNonNullElseGet 예제 String str3 = null; System.out.println(Objects.requireNonNullElseGet(str3, () -> "Supplier 문자열")); // "Supplier 문자열" // checkIndex 예제 try { List<Integer> list = Collections.singletonList(1); int index = Objects.checkIndex(1, list.size()); // IndexOutOfBoundsException 발생 } catch (IndexOutOfBoundsException e) { System.out.println("유효하지 않은 인덱스입니다."); }
Java
복사

java.util.Comparator

NOTE
Comparator는 객체를 비교하는 매커니즘을 제공합니다. 주로 컬렉션 프레임워크에서 객체 정렬, 순서 관리에서 주로 사용됩니다.
List<String> animals = new ArrayList<>(); animals.add("Dog"); animals.add("Elephant"); animals.add("Cat"); // Comparator 람다 표현식 Collections.sort(animals, Comparator.comparingInt(String::length)); System.out.println(animals); // [Dog, Cat, Elephant] // naturalOrder 기본정렬 Collections.sort(animals, Comparator.comparingInt(String::length) .thenComparing(Comparator.naturalOrder())); System.out.println(animals); // [Cat, Dog, Elephant] // reversed 역정렬 Collections.sort(animals, Comparator.comparingInt(String::length) .reversed()); System.out.println(animals); // [Elephant, Cat, Dog]
Java
복사

java.util.Arrays

NOTE
Arrays는 배열 구조를 조작, 변환, 정렬, 검색하는 정적 메서드들을 제공해줍니다!
// 배열 정렬(sort) int[] numbers = {3, 1, 4, 1, 5, 9}; Arrays.sort(numbers); System.out.println("Sorted numbers: " + Arrays.toString(numbers)); // 출력: Sorted numbers: [1, 1, 3, 4, 5, 9] // 이진 검색(binarySearch) int index = Arrays.binarySearch(numbers, 4); System.out.println("Index of 4: " + index); // 출력: Index of 4: 3 // 배열 복사(copyOf) int[] copiedNumbers = Arrays.copyOf(numbers, numbers.length); System.out.println("Copied array: " + Arrays.toString(copiedNumbers)); // 출력: Copied array: [1, 1, 3, 4, 5, 9] // 배열 채우기(fill) Arrays.fill(copiedNumbers, 7); System.out.println("Array filled with 7: " + Arrays.toString(copiedNumbers)); // 출력: Array filled with 7: [7, 7, 7, 7, 7, 7] // 배열을 리스트로 변환(asList) String[] names = {"Alice", "Bob", "Charlie"}; System.out.println("Names list: " + Arrays.asList(names)); // 출력: Names list: [Alice, Bob, Charlie]
Java
복사

java.util.Collections

NOTE
Objects는 객체에 대한 일반적인 연산을 수행하는 정적 메서드들을 제공해 다양한 연산을 쉽게 처리할 수 있게 도와주는 유틸리티 클래스입니다.
// 리스트 정렬(sort) List<String> fruits = new ArrayList<>(); fruits.add("Pineapple"); fruits.add("Apple"); fruits.add("Orange"); Collections.sort(fruits); System.out.println("Sorted fruits: " + fruits); // 출력: Sorted fruits: [Apple, Orange, Pineapple] // 리스트 셔플 (shuffle) Collections.shuffle(fruits); System.out.println("Shuffled fruits: " + fruits); // 출력: Shuffled fruits: [Pineapple, Apple, Orange] (출력은 실행할 때마다 달라질 수 있음) // 리스트 뒤집기(reverse) Collections.reverse(fruits); System.out.println("Reversed fruits: " + fruits); // 출력: Reversed fruits: [Orange, Apple, Pineapple] (셔플된 상태에 따라 다를 수 있음) // 최대값, 최소값 찾기(max, min) System.out.println("Max fruit: " + Collections.max(fruits)); System.out.println("Min fruit: " + Collections.min(fruits)); // 출력: Max fruit: Pineapple // 출력: Min fruit: Apple
Java
복사

java.util.Collectors

NOTE
Objects는 객체에 대한 일반적인 연산을 수행하는 정적 메서드들을 제공해 다양한 연산을 쉽게 처리할 수 있게 도와주는 유틸리티 클래스입니다.
// 리스트 수집 Stream<String> names = Stream.of("John", "Paul", "George", "Ringo"); List<String> nameList = names.collect(Collectors.toList()); System.out.println(nameList); // [John, Paul, George, Ringo] // 길이별 문자열 그룹화 Stream<String> namesForGrouping = Stream.of("John", "Paul", "George", "Ringo"); Map<Integer, List<String>> nameByLength = namesForGrouping.collect(Collectors.groupingBy(String::length)); System.out.println(nameByLength); // {4=[John, Paul], 5=[Ringo], 6=[George]} // 문자열 조인 Stream<String> namesForJoin = Stream.of("John", "Paul", "George", "Ringo"); String joinNames = namesForJoin.collect(Collectors.joining(", ")); System.out.println(joinNames); // John, Paul, George, Ringo
Java
복사

java.util.Optional

NOTE
Optional 클래스는 null이 될 수 있는 값을 캡슐화하는 컨테이너 객체입니다.
Optional<String> optionalPresent = Optional.of("Present"); Optional<String> optionalEmpty = Optional.empty(); // 값이 존재하는 경우 출력 optionalPresent.ifPresent(name -> System.out.println("name = " + name)); // 값이 없는 경우 기본값 설정 String nameOrDefault = optionalEmpty.orElse("Default"); System.out.println("nameOrDefault = " + nameOrDefault); // 값이 있으면 가져오고, 없으면 새로운 Optional 생성 String value = optionalEmpty.orElseGet(() -> "New Value"); System.out.println("Value or New Value: " + value); // 값이 없을 때 에러 try { String valueOrThrow = optionalEmpty.orElseThrow(IllegalStateException::new); System.out.println(valueOrThrow); } catch (IllegalStateException e) { System.out.println(e.getMessage()); }
Java
복사