1. 개요
Apache Commons Lang 3 라이브러리 는 Java API의 기능 확장을 목표로하는 인기 있고 모든 기능을 갖춘 유틸리티 클래스 패키지입니다 .
라이브러리의 레퍼토리는 문자열, 배열 및 숫자 조작, 반영 및 동시성에서 쌍 및 트리플 (일반적으로 튜플 이라고 함)과 같은 여러 순서가 지정된 데이터 구조의 구현에 이르기까지 매우 풍부 합니다.
이 예제에서는 라이브러리의 가장 유용한 유틸리티 클래스에 대해 자세히 알아 봅니다.
2. Maven 의존성
평소와 같이 Apache Commons Lang 3 사용을 시작하려면 먼저 Maven 의존성 을 추가해야합니다 .
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
3. StringUtils 클래스
이 입문 요약에서 다룰 첫 번째 유틸리티 클래스는 StringUtils 입니다.
이름에서 알 수 있듯이 StringUtils를 사용하면 java.lang.String 이 즉시 제공하는 작업을 보완 / 확장하는 일련 의 null-safe s trings 작업 을 수행 할 수 있습니다 .
문자열 이 공백인지, 비어 있는지 , 소문자인지, 대문자인지, 영숫자 인지 확인하는 것과 같이 주어진 문자열 에 대해 여러 가지 검사를 수행하는 유틸리티 메소드 세트를 보여 드리겠습니다 .
@Test
public void whenCalledisBlank_thenCorrect() {
assertThat(StringUtils.isBlank(" ")).isTrue();
}
@Test
public void whenCalledisEmpty_thenCorrect() {
assertThat(StringUtils.isEmpty("")).isTrue();
}
@Test
public void whenCalledisAllLowerCase_thenCorrect() {
assertThat(StringUtils.isAllLowerCase("abd")).isTrue();
}
@Test
public void whenCalledisAllUpperCase_thenCorrect() {
assertThat(StringUtils.isAllUpperCase("ABC")).isTrue();
}
@Test
public void whenCalledisMixedCase_thenCorrect() {
assertThat(StringUtils.isMixedCase("abC")).isTrue();
}
@Test
public void whenCalledisAlpha_thenCorrect() {
assertThat(StringUtils.isAlpha("abc")).isTrue();
}
@Test
public void whenCalledisAlphanumeric_thenCorrect() {
assertThat(StringUtils.isAlphanumeric("abc123")).isTrue();
}
물론, StringUtils 클래스는 다른 많은 메서드를 구현하는데, 여기서는 단순함을 위해 생략했습니다.
특정 문자열 에 대해 특정 유형의 변환 알고리즘을 확인하거나 적용하는 다른 추가 방법에 대해서는 이 사용방법(예제) 를 확인하십시오 .
위에서 다룬 내용은 매우 간단하므로 단위 테스트는 자명해야합니다.
4. ArrayUtils 클래스
ArrayUtils의 클래스가 구현 우리가 처리하고 다양한 모양과 형태의 배열을 확인할 수 있도록 유틸리티 메소드의 배치 .
toString () 메서드 의 두 가지 오버로드 된 구현으로 시작해 보겠습니다.이 메서드 는 지정된 배열 의 문자열 표현 과 배열 이 null 일 때 특정 문자열 을 반환합니다 .
@Test
public void whenCalledtoString_thenCorrect() {
String[] array = {"a", "b", "c"};
assertThat(ArrayUtils.toString(array))
.isEqualTo("{a,b,c}");
}
@Test
public void whenCalledtoStringIfArrayisNull_thenCorrect() {
assertThat(ArrayUtils.toString(null, "Array is null"))
.isEqualTo("Array is null");
}
다음으로 hasCode () 및 toMap () 메서드가 있습니다.
전자 는 배열에 대한 사용자 정의 hashCode 구현을 생성 하고 후자는 배열 을 Map으로 변환합니다 .
@Test
public void whenCalledhashCode_thenCorrect() {
String[] array = {"a", "b", "c"};
assertThat(ArrayUtils.hashCode(array))
.isEqualTo(997619);
}
@Test
public void whenCalledtoMap_thenCorrect() {
String[][] array = {{"1", "one", }, {"2", "two", }, {"3", "three"}};
Map map = new HashMap();
map.put("1", "one");
map.put("2", "two");
map.put("3", "three");
assertThat(ArrayUtils.toMap(array))
.isEqualTo(map);
}
마지막으로 isSameLength () 및 indexOf () 메서드를 살펴 보겠습니다 .
전자는 두 배열의 길이가 같은지 확인하는 데 사용되며 후자는 주어진 요소의 인덱스를 가져 오는 데 사용됩니다.
@Test
public void whenCalledisSameLength_thenCorrect() {
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
assertThat(ArrayUtils.isSameLength(array1, array2))
.isTrue();
}
@Test
public void whenCalledIndexOf_thenCorrect() {
int[] array = {1, 2, 3};
assertThat(ArrayUtils.indexOf(array, 1, 0))
.isEqualTo(0);
}
StringUtils 클래스 와 마찬가지로 ArrayUtils 는 훨씬 더 많은 추가 메서드를 구현합니다. 이 사용방법(예제) 에서 이에 대해 자세히 알아볼 수 있습니다 .
이 경우에는 가장 대표적인 것만 선보였습니다.
5. NumberUtils 클래스
Apache Commons Lang 3의 또 다른 핵심 구성 요소는 NumberUtils 클래스입니다.
예상대로이 클래스는 숫자 유형을 처리하고 조작하는 것을 목표로하는 광범위한 유틸리티 메서드를 제공합니다 .
int 와 long 과 같은 다른 프리미티브의 동등성을 비교하는 compare () 메서드 의 오버로드 된 구현을 살펴 보겠습니다 .
@Test
public void whenCalledcompareWithIntegers_thenCorrect() {
assertThat(NumberUtils.compare(1, 1))
.isEqualTo(0);
}
@Test
public void whenCalledcompareWithLongs_thenCorrect() {
assertThat(NumberUtils.compare(1L, 1L))
.isEqualTo(0);
}
또한 위의 예제와 매우 유사하게 작동하는 byte 및 short 에서 작동하는 compare () 구현이 있습니다 .
이 리뷰의 다음은 createNumber () 및 isDigit () 메서드입니다.
첫 번째는 문자열 의 숫자 표현을 만들 수있게 해주는 반면, 두 번째는 문자열 이 숫자로만 구성되어 있는지 확인합니다 .
@Test
public void whenCalledcreateNumber_thenCorrect() {
assertThat(NumberUtils.createNumber("123456"))
.isEqualTo(123456);
}
@Test
public void whenCalledisDigits_thenCorrect() {
assertThat(NumberUtils.isDigits("123456")).isTrue();
}
제공된 배열의 혼합 및 최대 값을 찾을 때 NumberUtils 클래스는 min () 및 max () 메서드 의 오버로드 된 구현을 통해 이러한 작업에 대한 강력한 지원을 제공 합니다.
@Test
public void whenCalledmaxwithIntegerArray_thenCorrect() {
int[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.max(array))
.isEqualTo(6);
}
@Test
public void whenCalledminwithIntegerArray_thenCorrect() {
int[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.min(array)).isEqualTo(1);
}
@Test
public void whenCalledminwithByteArray_thenCorrect() {
byte[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.min(array))
.isEqualTo((byte) 1);
}
6. 분수 클래스
우리가 펜과 종이를 사용할 때 분수로 작업하는 것은 모두 괜찮습니다. 그러나 코드를 작성할 때이 프로세스의 복잡성을 겪어야합니까? 별로.
분수 클래스 감산하고 바람 분획 승산 가산한다 :
@Test
public void whenCalledgetFraction_thenCorrect() {
assertThat(Fraction.getFraction(5, 6)).isInstanceOf(Fraction.class);
}
@Test
public void givenTwoFractionInstances_whenCalledadd_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(1, 4);
Fraction fraction2 = Fraction.getFraction(3, 4);
assertThat(fraction1.add(fraction2).toString()).isEqualTo("1/1");
}
@Test
public void givenTwoFractionInstances_whenCalledsubstract_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(3, 4);
Fraction fraction2 = Fraction.getFraction(1, 4);
assertThat(fraction1.subtract(fraction2).toString()).isEqualTo("1/2");
}
@Test
public void givenTwoFractionInstances_whenCalledmultiply_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(3, 4);
Fraction fraction2 = Fraction.getFraction(1, 4);
assertThat(fraction1.multiplyBy(fraction2).toString()).isEqualTo("3/16");
}
분수를 사용한 작업이 일상적인 개발 작업에서 가장 빈번한 작업은 아니지만 Fraction 클래스는 이러한 작업을 간단한 방식으로 수행하는 데 유용한 지원을 제공합니다.
7. SystemUtils 클래스
때로는 기본 Java 플랫폼 또는 운영 체제의 다양한 속성 및 변수에 대한 동적 정보를 얻어야합니다.
Apache Commons Lang 3 은이 를 쉽게 수행 할 수있는 SystemUtils 클래스 를 제공합니다 .
예를 들어 getJavaHome () , getUserHome () 및 isJavaVersionAtLeast () 메소드를 고려해 보겠습니다 .
@Test
public void whenCalledgetJavaHome_thenCorrect() {
assertThat(SystemUtils.getJavaHome())
.isEqualTo(new File("path/to/java/jdk"));
}
@Test
public void whenCalledgetUserHome_thenCorrect() {
assertThat(SystemUtils.getUserHome())
.isEqualTo(new File("path/to/user/home"));
}
@Test
public void whenCalledisJavaVersionAtLeast_thenCorrect() {
assertThat(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_RECENT)).isTrue();
}
SystemUtils 클래스가 구현 하는 몇 가지 추가 유틸리티 메서드가 있습니다. 예제를 짧게 유지하기 위해 생략했습니다.
8. Lazy 초기화와 빌더 클래스
Apache Commons Lang 3의 가장 매력적인 측면 중 하나는 지연 초기화 및 빌더 패턴을 포함하여 잘 알려진 디자인 패턴을 구현하는 것입니다 .
예를 들어 값 비싼 User 클래스 (간결성을 위해 표시되지 않음)를 만들고 실제로 필요할 때까지 인스턴스화를 연기 한다고 가정 해 보겠습니다 .
이 경우 매개 변수화 된 LazyInitializer 추상 클래스 를 확장 하고 initialize () 메서드를 재정의하기 만하면됩니다 .
public class UserInitializer extends LazyInitializer<User> {
@Override
protected User initialize() {
return new User("John", "john@domain.com");
}
}
이제 필요할 때 비용이 많이 드는 User 객체 를 얻으려면 UserInitializer의 get () 메서드를 호출하면됩니다 .
@Test
public void whenCalledget_thenCorrect()
throws ConcurrentException {
UserInitializer userInitializer = new UserInitializer();
assertThat(userInitializer.get()).isInstanceOf(User.class);
}
GET () 에 규정 된 방법은 인스턴스 필드의 이중 체크 관용구 (스레드 안전)의 구현입니다 조슈아 블로흐의 "효과적인 자바", 항목 71 :
private volatile User instance;
User get() {
if (instance == null) {
synchronized(this) {
if (instance == null)
instance = new User("John", "john@domain.com");
}
}
}
return instance;
}
또한 Apache Commons Lang 3은 HashCodeBuilder 클래스를 구현합니다 .이를 통해 일반적인 유창한 API를 기반으로 빌더에 다른 매개 변수를 제공하여 hashCode () 구현 을 생성 할 수 있습니다 .
@Test
public void whenCalledtoHashCode_thenCorrect() {
int hashcode = new HashCodeBuilder(17, 37)
.append("John")
.append("john@domain.com")
.toHashCode();
assertThat(hashcode).isEqualTo(1269178828);
}
BasicThreadFactory 클래스를 사용하여 비슷한 작업을 수행 하고 이름 지정 패턴과 우선 순위를 가진 데몬 스레드를 만들 수 있습니다.
@Test
public void whenCalledBuilder_thenCorrect() {
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("workerthread-%d")
.daemon(true)
.priority(Thread.MAX_PRIORITY)
.build();
assertThat(factory).isInstanceOf(BasicThreadFactory.class);
}
9. ConstructorUtils 클래스
Reflection은 Apache Commons Lang 3에서 일류 시민입니다.
라이브러리에는 여러 리플렉션 클래스가 포함되어있어 클래스 필드 및 메서드에 반사적으로 액세스하고 조작 할 수 있습니다.
예를 들어, 순진한 User 도메인 클래스를 구현했다고 가정 해 보겠습니다 .
public class User {
private String name;
private String email;
// standard constructors / getters / setters / toString
}
매개 변수화 된 생성자가 public 이라고 가정하면 ConstructorUtils 클래스를 사용하여 쉽게 액세스 할 수 있습니다 .
@Test
public void whenCalledgetAccessibleConstructor_thenCorrect() {
assertThat(ConstructorUtils
.getAccessibleConstructor(User.class, String.class, String.class))
.isInstanceOf(Constructor.class);
}
생성자를 통한 표준 클래스 인스턴스화 대신 invokeConstructor () 및 invokeExactConstructor () 메서드를 호출하여 반사적으로 User 인스턴스를 만들 수 있습니다 .
@Test
public void whenCalledinvokeConstructor_thenCorrect()
throws Exception {
assertThat(ConstructorUtils.invokeConstructor(User.class, "name", "email"))
.isInstanceOf(User.class);
}
@Test
public void whenCalledinvokeExactConstructor_thenCorrect()
throws Exception {
String[] args = {"name", "email"};
Class[] parameterTypes= {String.class, String.class};
assertThat(ConstructorUtils.invokeExactConstructor(User.class, args, parameterTypes))
.isInstanceOf(User.class);
}
10. FieldUtils 클래스
마찬가지로 클래스 필드를 반사적으로 읽고 / 쓰기 위해 FieldUtils 클래스 의 메서드를 사용할 수 있습니다 .
User 클래스의 필드 또는 결국 클래스가 수퍼 클래스에서 상속 하는 필드를 가져오고 싶다고 가정 해 보겠습니다 .
이 경우 getField () 메서드를 호출 할 수 있습니다 .
@Test
public void whenCalledgetField_thenCorrect() {
assertThat(FieldUtils.getField(User.class, "name", true).getName())
.isEqualTo("name");
}
또는 더 제한적인 리플렉션 범위를 사용하고 User 클래스 에서 선언 된 필드 만 가져 오고 수퍼 클래스에서 상속되지 않으 려면 getDeclaredField () 메서드를 사용하면됩니다 .
@Test
public void whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName())
.isEqualTo("name");
}
또한 getAllFields () 메서드를 사용하여 반영된 클래스의 필드 수를 가져오고 writeField () 및 writeDeclaredField () 메서드 를 사용하여 선언 된 필드 또는 계층 구조에 정의 된 필드에 값을 쓸 수 있습니다.
@Test
public void whenCalledgetAllFields_thenCorrect() {
assertThat(FieldUtils.getAllFields(User.class).length)
.isEqualTo(2);
}
@Test
public void whenCalledwriteField_thenCorrect()
throws IllegalAccessException {
FieldUtils.writeField(user, "name", "Julie", true);
assertThat(FieldUtils.readField(user, "name", true))
.isEqualTo("Julie");
}
@Test
public void givenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect() throws IllegalAccessException {
FieldUtils.writeDeclaredField(user, "name", "Julie", true);
assertThat(FieldUtils.readField(user, "name", true))
.isEqualTo("Julie");
}
11. MethodUtils 클래스
같은 줄을 따라 MethodUtils 클래스를 사용하여 클래스 메서드에 대한 리플렉션을 사용할 수 있습니다 .
이 경우 User 클래스의 getName () 메서드 의 가시성 은 public 입니다. 따라서 getAccessibleMethod () 메서드를 사용하여 액세스 할 수 있습니다 .
@Test
public void whenCalledgetAccessibleMethod_thenCorrect() {
assertThat(MethodUtils.getAccessibleMethod(User.class, "getName"))
.isInstanceOf(Method.class);
}
반사적으로 메서드를 호출하는 경우 invokeExactMethod () 및 invokeMethod () 메서드를 사용할 수 있습니다 .
@Test
public
void whenCalledinvokeExactMethod_thenCorrect()
throws Exception {
assertThat(MethodUtils.invokeExactMethod(new User("John", "john@domain.com"), "getName"))
.isEqualTo("John");
}
@Test
public void whenCalledinvokeMethod_thenCorrect()
throws Exception {
User user = new User("John", "john@domain.com");
Object method = MethodUtils.invokeMethod(user, true, "setName", "John");
assertThat(user.getName()).isEqualTo("John");
}
12. MutableObject 클래스
불변성 은 가능한 모든 경우에 기본값으로 설정해야하는 좋은 객체 지향 소프트웨어의 핵심 기능 이지만 , 안타깝게도 때때로 변경 가능한 객체를 처리해야합니다.
또한 변경 가능한 클래스를 만들려면 많은 상용구 코드가 필요하며 대부분의 IDE에서 자동 생성 된 setter를 통해 생성 할 수 있습니다.
이를 위해 Apache Commons Lang 3은 최소한 의 번거 로움으로 변경 가능한 객체를 생성하기위한 간단한 래퍼 클래스 인 MutableObject 클래스를 제공합니다 .
@BeforeClass
public static void setUpMutableObject() {
mutableObject = new MutableObject("Initial value");
}
@Test
public void whenCalledgetValue_thenCorrect() {
assertThat(mutableObject.getValue()).isInstanceOf(String.class);
}
@Test
public void whenCalledsetValue_thenCorrect() {
mutableObject.setValue("Another value");
assertThat(mutableObject.getValue()).isEqualTo("Another value");
}
@Test
public void whenCalledtoString_thenCorrect() {
assertThat(mutableObject.toString()).isEqualTo("Another value");
}
물론 이것은 MutableObject 클래스 를 사용하는 방법의 예일뿐입니다 .
경험상 불변 클래스를 만들려고 항상 노력해야하며 최악의 경우 필요한 수준의 가변성 만 제공해야합니다 .
13. MutablePair 클래스
흥미롭게도 Apache Commons Lang 3은 쌍과 삼중의 형태로 튜플에 대한 강력한 지원을 제공합니다.
따라서 순서가 지정된 요소의 가변 쌍을 만들어야한다고 가정 해 보겠습니다.
이 경우 MutablePair 클래스를 사용합니다 .
private static MutablePair<String, String> mutablePair;
@BeforeClass
public static void setUpMutablePairInstance() {
mutablePair = new MutablePair<>("leftElement", "rightElement");
}
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(mutablePair.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(mutablePair.getRight()).isEqualTo("rightElement");
}
@Test
public void whenCalledsetLeft_thenCorrect() {
mutablePair.setLeft("newLeftElement");
assertThat(mutablePair.getLeft()).isEqualTo("newLeftElement");
}
여기서 강조 할 가치가있는 가장 관련성있는 세부 사항은 클래스의 깨끗한 API입니다.
표준 setter / getter를 통해 쌍으로 래핑 된 왼쪽 및 오른쪽 개체를 설정하고 액세스 할 수 있습니다.
14. ImmutablePair 클래스
당연히 ImmutablePair 라는 MutablePair 클래스 의 불변의 대응 구현도 있습니다 .
private static ImmutablePair<String, String> immutablePair = new ImmutablePair<>("leftElement", "rightElement");
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(immutablePair.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(immutablePair.getRight()).isEqualTo("rightElement");
}
@Test
public void whenCalledof_thenCorrect() {
assertThat(ImmutablePair.of("leftElement", "rightElement"))
.isInstanceOf(ImmutablePair.class);
}
@Test(expected = UnsupportedOperationException.class)
public void whenCalledSetValue_thenThrowUnsupportedOperationException() {
immutablePair.setValue("newValue");
}
불변 클래스에서 예상 할 수 있듯이 setValue () 메서드를 통해 쌍의 내부 상태를 변경하려고 하면 UnsupportedOperationException 예외가 발생합니다.
15 배 클래스
여기서 살펴볼 마지막 유틸리티 클래스는 Triple 입니다.
클래스가 추상이므로 of () 정적 팩토리 메서드 를 사용하여 Triple 인스턴스를 만들 수 있습니다 .
@BeforeClass
public static void setUpTripleInstance() {
triple = Triple.of("leftElement", "middleElement", "rightElement");
}
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(triple.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetMiddle_thenCorrect() {
assertThat(triple.getMiddle()).isEqualTo("middleElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(triple.getRight()).isEqualTo("rightElement");
}
MutableTriple 및 ImmutableTriple 클래스를 통해 변경 가능한 트리플과 변경 불가능한 트리플 모두에 대한 구체적인 구현도 있습니다.
정적 팩토리 메서드가 아닌 매개 변수화 된 생성자를 통해 인스턴스를 만들 수 있습니다.
이 경우 API가 MutablePair 및 ImmutablePair 클래스 의 API와 매우 유사 해 보이므로 건너 뛰겠습니다 .
16. 결론
이 예제에서, 우리는 아파치 코 몬즈 랭 3가 제공하는 가장 유용한 유틸리티 클래스의 일부에서 자세히 살펴했다 떨어져 선반 .
라이브러리는 살펴볼 가치가있는 다른 많은 유틸리티 클래스를 구현 합니다. 여기에서 우리는 매우 독단적 인 기준에 따라 가장 유용한 것을 보여주었습니다.
전체 라이브러리 API는 공식 Javadocs 를 확인하십시오 .