# 인터페이스의 변화

이번주에 혹한기 훈련을 다녀왔는데.. 너무 추웠다.. 감기 걸린거 같다..

# java8의 인터페이스

# default Method

  • java8에서 새로 추가된 기능으로 인터페이스에 기본 메소드를 정의할 수 있게 되었다.
  • 기본메소드를 정의하는 이유는 인터페이스를 구현하는 구현체들이 공통된 역할을 수행하는 메소드를 사용하기 위함이다.
  • default로 추가해줌으로써 원래 인터페이스를 구현하고 있던 구현체에서 새로운 메소드를 정의할 필요가 없어진다.

# Default Method 구현 방법

public interface Foo {
    String getName();

    default void printUpperName() {
        System.out.println(getName().toUpperCase());
    }
}


1
2
3
4
5
6
7
8
9

위 처럼 default를 활용해 메소드를 interface에서 구현해 줄 수 있다. 이 인터페이스를 구현하는 구현체에서 따로 재정의 없이 메소드를 사용할 수 있다.

# default method 특징

  • 디폴트 메소드로 구현을 할 경우 개발자가 원하는 동작과 다르게 동작할 수 있다. 이는 @implSpec을 활용해 정확히 스팩을 명시해줌으로써 사용자가 개발자가 원하는 방향으로 사용할 수 있도록 유도해주는 것이 좋다.
  • Object에서 구현되어있는 메소드는 default로 재정의할 수 없다. java의 object 메소드의 예시로 toString이 있는데, 이 것은 default로 재정의가 불가하다.
  • interface를 상속받은 interface에서 default를 사용하기 싫다면, default를 추상메소드로 재정의 해주면 된다.
  • interface를 2개 받아서 구현하는 구현체에서 만약 default 메소드의 이름이 동일하게 있다면 컴파일 에러가 발생한다.

# Static Method

  • 자바8에서는 interface에 static method를 구현할 수 있다.
  • 기존 static과 동일하게 인터페이스의 명으로 static method에 접근이 가능하다.

# static method 사용 예시

public interface Foo {
    /**
     * interface에서 static 메소드를 구현하여 사용할 수 있다.
     */
    static void helloStatic(){
        System.out.println("Hello Static Method in interface");
    }
}

public static void main(String[] args) {
    Foo.helloStatic();
}
1
2
3
4
5
6
7
8
9
10
11
12

static method 구현 시 인터페이스의 이름으로 접근이 가능하게 된다.

# Iterable의 기본 메소드

Iterfable의 대표적인 기본 메소드로 foreach()와 spliterator()이 있다.

# foreach()

  • Collection :foreach()
  • foreach는 파라미터로 Consumer functional interface를 받는다.
  • consumer이기 때문에 값 하나를 받아서 소모를하게 된다.
        List<String> names = new ArrayList<>();
        names.add("kim jin seop");
        names.add("java8");
        names.add("spring");
        names.add("jpa");

        //리스트에 저장된 이름을 모두 출력해주기
        names.forEach((s) -> System.out.println(s));

        // 메소드 레퍼런스를 활용해서 구현할 수 있음
        System.out.println("<< 메소드 레퍼런스 활용해서 구현 >>");
        names.forEach(System.out::println);
1
2
3
4
5
6
7
8
9
10
11
12

# spliterable()

  • 동일하게 foreach처럼 동작할 수 있다.
  • 데이터를 쪼개서 사용할 수 있게 된다. 절반으로 쪼개어 진다.
  • 쪼개는 방법은 trySplit()을 사용하여준다. 데이터의 개수의 절반으로 쪼개어 준다.
  • tryAdvance를 활용해 실행할 수 있는데, 만약 다음 값이 있으면 true 없으면 false로 while을 사용해 순회할 수 있다.
  • 혹은 forEachRemaining()을 활용하여 모든 값들을 순회할 수 있다.(tryAdvance를 사용했다면 남은 구간을 모두 순회한다.)
  • 순서가 뒤 바뀌기 때문에 순서에 의미없는 메소드에 적용할 수 있다.
        //spliterator 정의
        Spliterator<String> sp1 = names.spliterator();
        //trySplit으로 절반 쪼개기(데이터를 반으로 쪼개어줌)
        //sp1에 있던 데이터의 절반을 가져오고 sp1에 절반 데이터가 옮겨짐
        Spliterator<String> sp2 = sp1.trySplit();

        //순회 방법1 forEachRemaining으로 남은 것 모두 순회
        sp1.forEachRemaining(System.out::println);
        //순회방법2 tryAdvance 사용
        while (sp2.tryAdvance(System.out::println));
1
2
3
4
5
6
7
8
9
10

# Collection의 기본 메소드

Collection에서 제공하는 다양한 기본 메소드에 대해 알아보겠다.

# stream()

  • Collection의 대표적인 기본 메소드로 strem()이 있다.
  • 매우 자주쓰이는 기본 메소드이다.
  • filter()로 걸러서 count()로 갯수를 셀수도 있고, list나 set으로 반환받을 수 있다.
  • 다음에 자세히 알아보도록 하겠다.
        //k로 시작하는 값들만 뽑아서 출력
        names.stream()
                .filter((s) -> s.startsWith("k"))
                .collect(Collectors.toList())
                .forEach(System.out::println);
1
2
3
4
5

# removeIf()

  • 파라미터로 Predicate을 받으며 일치하는 조건의 값을 지워주는 역할을 수행한다.
  • Predicate의 조건이 일치하는 값들을 모두 지워준다.
        names.removeIf(s -> s.equals("jpa"));
        names.forEach(System.out::println);
1
2

# Comparator의 기본 메소드

comparator는 정렬을 할 때 주로 사용해주는 Functional Interface이다.제공해주는 기본메소드를 알아보자.

# reversed()

  • 정렬을 역순으로 해주는 기본메소드이다.
  • 정렬을 역순으로 하고 싶다면 compareToIgnoreCase에 reversed()를 해주면 된다. 여기서 사용되는 reversed()는 default 메소드이다.
        Comparator<String> compareToIgnoreCase = String::compareToIgnoreCase;
        //정렬하기
        names.sort(compareToIgnoreCase);
        //역순으로 정렬하기
        names.sort(compareToIgnoreCase.reversed());
1
2
3
4
5

# thenComparing()

  • 정렬을 할 때 추가 조건을 부여할 때 사용한다.
        Comparator<String> ci = String::compareToIgnoreCase;
        names.sort(ci.thenComparing(Comparator.reverseOrder()));
1
2

# Comparator의 static 메소드

정렬을 위하여 다양한 static메소드를 제공하여준다.

  • naturalOrder() : 오름차순으로 정렬할 때 이용한다. 파라미터로 들어가는 값은 없으며 반환형은 Comparator이다.
  • reverseOrder() : 내림차순으로 정렬할 때 사용한다. 파라미터로 들어가는 값은 없으며 반환형은 Comparator이다.
  • nullsFirst() : null을 처음으로 오게 정렬할 때 사용한다. 파라미터로 Comparator 받는다(naturalOrder()나 reverseOrder()를 사용하면 된다.)
  • nullsLast() : null을 뒤로 정렬해줄 때 사용한다. 파라미터로 Comparator 받는다(naturalOrder()나 reverseOrder()를 사용하면 된다.)