반응형

JAVA8을 공부하면서 참 편하면서 활용도가 높다고 생각된 것 중 가장 크게 와닿은 함수적 인터페이스에 대해 알아보겠습니다.

 

public interface Function<T, R> { … }

Function 인터페이스는 파라미터 타입이 2개하나는 인자로, 하나는 리턴값으로 사용합니다. 또한, apply() 추상 메소드를 상속 받아 사용하고 기본 메소드로 andThen(), compose() 메소드를 사용합니다.

 

처음으로 사용 예시를 봤던 방식이 널 체크하는 예제였습니다.

보면서 가독성 면이나 사용법을 보면서 "와 편하다..."라고 생각이 되었습니다.

매번 com.~.~.utils에 있는 수많은 문자열 처리 함수들이 한줄 한줄로 처리 할 수 있고, 구분도 명확하게 느껴졌습니다.

 

바로 소스를 보겠습니다.

 

 

 


NVL 널체크

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	
	public static void main(String[] args) {
		System.out.println("일반 함수 >" + NVL(null)); //일반 문자열 함수
		System.out.println("함수형 인터페이스" + NVL.apply(null)); //함수형 인터페이스
		
		System.out.println("일반 함수 >" + NVL("TEST"));
		System.out.println("함수형 인터페이스" + NVL.apply("TEST"));
		
		System.out.println("일반 함수 >" + NVL(""));
		System.out.println("함수형 인터페이스" + NVL.apply(""));
	}
	
	public static String NVL(String str) {
		String res = "";
		if(str != null && !str.trim().equals("")) {
			res = str;
		}
		return res;
	}
}

일반 함수와 함수형 인터페이스의 사용 비교

일반 함수 NVL과 함수형 인터페이스 NVL을 통해 비교를 해봤습니다.

그렇게 어렵지 않은 문자열이 null인지 공백값인지 확인 후 return값을 출력하는 예제입니다.

 

둘다 동일하게 동작하는 것을 볼 수 있습니다.

 

사용법에 차이가 있다면 함수형 인터페이스 Functionapply() 추상메소드를 상속받습니다.

차이점으로 코딩 줄 수의 차이는 조금 애매한 것 같습니다. 똑같이 선언하고 return에서 삼항연산자 처리를 하면 동일하기 때문입니다.

 

다른 예제를 보겠습니다.

 

 

 


문자열 숫자를 정수형으로 반환

import java.util.function.Function;

public class FunctionC {
	
	final static Function<String, Integer> toInt = str -> str.length() == 0 ? 0 : Integer.parseInt(str);
	
	public static void main(String[] args) {
		System.out.println(toInt.apply("555"));
	}
}

변환

 

문자열 숫자 데이터를 정수형으로 반환하는 예제입니다.

 

문제없이 동작하는것을 볼 수 있습니다. 하지만 문자열에는 null데이터가 존재합니다.

그럼 함수형 인터페이스에 null체크 로직을 삼항연산자 앞부분에 추가할까요? 그렇게 해도 상관은 없지만 함수형 인터페이스는 연결해서 사용이 가능합니다.

 

바로 아래처럼 말이죠.

 

 


Function.andThen()

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	final static Function<String, Integer> toInt = str -> str.length() == 0 ? 0 : Integer.parseInt(str);
	
	public static void main(String[] args) {
		System.out.println(toInt.apply("555"));
		System.out.println(NVL.andThen(toInt).apply(null));
	}
}

null 데이터는 0이 나옴

null을 넣었지만 널포인트 에러가 아닌 0이 나온 것을 볼 수 있습니다.

바로 전 예제에서 만든 NVL 함수형 인터페이스를 통해 먼저 널체크를 하고 andThen() 메소드를 통해 문자열을 숫자로 변환하는 함수형 인터페이스를 연결해줍니다.

 

하지만 사용하면서 주의할 점이 있습니다.

당연한거지만 연결하는 순서도 차례대로 진행해야 합니다. 널체크를 먼저 하고 사용하고자 하는 함수형 인터페이스를 사용해야 합니다.

 

 

 

 

andThen()메소드의 잘 못된 연결방식? compose() !

import java.util.function.Function;

public class FunctionC {
	
	final static Function<Object, String> NVL = str -> str != null && !((String) str).trim().equals("") ? str.toString() : "";
	
	final static Function<Object, String> UPPERCASE = str -> ((String) str).toUpperCase();
	
	public static void main(String[] args) {
		System.out.println("andThen >" + NVL.andThen(UPPERCASE).apply("hello world!!!")); //잘 못된 문법 NULL을 먼저 체크해야 합니다.
		
		System.out.println();
		System.out.println();
		System.out.println();
		
		System.out.println("잘 못 된 문법 >" + UPPERCASE.andThen(NVL).apply(null)); //잘 못된 문법 NULL을 먼저 체크해야 합니다.
	}
}

연결 순서를 잘 못 연결하면 원하는 결과를 얻지 못한다.

 

또 다른 예제입니다. 이번엔 널체크와 문자열을 대문자로 변경하는 toUpperCase() 메소드를 연결하였습니다.

널체크를 먼저한 경우엔 문제가 없지만 아래처럼 강제로 null데이터를 꺼꾸로 입력한 경우엔 null데이터를 가지고 대문자로 변환을 하다보니 null 예외처리가 발생하는 것을 볼 수 있습니다.

 

하지만, 동작 순서를 반대로 하고 싶은 경우도 있을 것 같습니다.

처음에 시작할때 기본 메소드로 andThen()compose()가 존재한다고 했는데 여기서 compose() 메소드를 사용하면 정상적으로 동작이 됩니다.

 

 

 

 

compose()

System.out.println("잘 못 된 문법 >" + UPPERCASE.compose(NVL).apply("hello world~~~")); //잘 못된 문법 NULL을 먼저 체크해야 합니다.

compose()는 동작한다.

 

기본 null에러 발생하던부분의 andThen()compose()로만 변경해주었습니다.

andThen()의 방식이 1 -> 2 라면 compose()는 2 -> 1로 동작합니다.

즉, 내부에 있는 NVL 인터페이스가 먼저 동작하고 UPPERCASE 인터페이스가 동작해서 정상적으로 hello world~~~이 대문자로 변경되었습니다.

 

반응형