Defualt Method
- 디폴트 메소드는 자바8 에서 더 유연하게 인터페이스를 만들 수 있도록 추가한 방법이다.
- 자바 8 이전에는 인터페이스의 메소드는 반드시 모두 상속해야만 했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | interface Calcuator { default void add(int a, int b) { System.out.println((a+b)); } default void minus(int a, int b) { System.out.println((a-b)); } } public class Test implements Calcuator{ public void cal(){ add(3,5); } } | cs |
위와 같은 방법으로 상속받은 Calculator 인터페이스는 add, minus 라는 디폴트 메소드를 호출 할 수 있다.
또한 그동안 자바에서는 다중상속이 불가능한 것으로 알려져 있던 것을, 디폴트 메소드를 통해 어느정도 구현할 수 있다. 하지만 다이아몬드 상속 문제를 반드시 피해야 하는데 만일 인지하지 못할 경우 다음과 같은 컴파일 에러가 날 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | interface Calcuator { default void add(int a, int b) { System.out.println((a+b)); } default void minus(int a, int b) { System.out.println((a-b)); } } interface DoubleCalculator { default void add(int a, int b) { System.out.println((a+b)*2); } default void minus(int a, int b) { System.out.println((a-b)*2); } } /** * 디폴트 메소드로 인해 어느 정도 다중 상속 개념이 될 수 있다. 다이아모몬드 상속 문제를 피해야한다. */ public class DefaultMethod implements Calcuator, DoubleCalculator{ public void cal() { add(3,5); minus(3,6); } } | cs |
위와 같은 경우, 컴파일 시 에러가 나는데 Interface의 상속을 통해 Override를 통해 문제를 해결할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | interface Calcuator { default void add(int a, int b) { System.out.println((a+b)); } default void minus(int a, int b) { System.out.println((a-b)); } } interface DoubleCalculator { default void add(int a, int b) { System.out.println((a+b)*2); } default void minus(int a, int b) { System.out.println((a-b)*2); } } interface CalAndDoubleCal extends Calcuator,DoubleCalculator{ @Override default void add(int a, int b){ Calcuator.super.add(a,b); DoubleCalculator.super.add(a,b); }; @Override default void minus(int a, int b) { Calcuator.super.minus(a,b); DoubleCalculator.super.minus(a,b); } } public class DefaultMethod implements CalAndDoubleCal{ public void cal(){ add(3,5); } } | cs |
함수형 인터페이스(Functinal Interface)
- 오직 하나의 추상 메소드를 지정한다.
- @Functional Interface 를 붙이는 것을 권장한다.
- 람다식 사용 가능
Predicate<T>
Java.util API 내부를 살펴보면 test라는 하나의 추상 메소드만 지정된다. test는 제네릭 형식의 T 객체를 인수로 받아 boolean을 반환한다.
또한 Predicate 인터페이스는 복작한 predicate를 만들 수 있도록 negate, and, or 메소드를 제공하는데 이는 default 메소드이다.
1 2 3 4 5 6 7 8 | //predicate Predicate<String> nonEmptyString = s -> !s.isEmpty(); Predicate<String> emptyString = s -> s.isEmpty(); System.err.println(nonEmptyString.test("")); //false System.err.println(nonEmptyString.and(emptyString).test("")); //두개의 조건을 모두 만족해야하므로 false System.err.println(nonEmptyString.or(emptyString).test("")); //둘중 하나만 만족해도 되므로 true System.err.println(nonEmptyString.negate().test("")); // nonEmpytyString predicate의 반대상황을 테스트 true | cs |
Consumer<T>
Java.util API 내부를 살펴보면 accept라는 하나의 추상 메소드만 지정된다. accept는 제네릭 형식의 T 객체를 인수로 받아 void을 반환한다.
1 2 3 4 5 6 7 | //consumer Consumer<String> outConsumer = s -> System.out.println(s); Consumer<String> errConsumer = s -> System.err.println(s); outConsumer.accept("k"); //k outConsumer.andThen(errConsumer).accept("g"); // g, g | cs |
Function<T,R>
Java.util API 내부를 살펴보면 aaply라는 하나의 추상 메소드만 지정된다. appy는 제네릭 형식의 T 객체를 인수로 받아 제네릭 형태의 R객체를 반환한다.
1 2 3 4 5 6 7 | //function Function<String,String> lowerFunction = s -> s.toLowerCase(); Function<String,String> upperFunction = s -> s.toUpperCase(); System.out.println(lowerFunction.apply("S")); //s System.out.println(lowerFunction.andThen(upperFunction).apply("S")); // S | cs |
'programming > Java' 카테고리의 다른 글
primitive type과 boxed primitives (0) | 2019.11.24 |
---|---|
Reflection (0) | 2019.09.20 |
[JAVA 8] - 함수형 프로그래밍(Functional Programming) (0) | 2019.02.17 |
# Enum (열거형) (0) | 2018.05.20 |
# NIO - Selector (0) | 2018.05.19 |