공부일기/Java 8

Java 8 - 2. 인터페이스의 변화

Youngbin Kim 2020. 12. 7. 20:17

 

1. 인터페이스 기본 메소드와 스태틱 메소드

  • 기본 메소드 (Default Methods)
    • 인터페이스에 메소드 선언이 아니라 구현체를 제공하는 방법

    • 해당 인터페이스를 구현한 클래스를 깨트리지 않고 새 기능을 추가할 수 있다.

    • 기본 메소드는 구현체가 모르게 추가된 기능으로 그만큼 리스크가 있다.

      • 컴파일 에러는 아니지만 구현체에 따라 런타임 에러가 발생할 수 있다.

      • 반드시 문서화 할 것. (@implSpec 자바독 태그 사용)

    • Object가 제공하는 기능 (equals, hasCode)는 기본 메소드로 제공할 수 없다.

      • 구현체가 재정의해야 한다.

    • 본인이 수정할 수 있는 인터페이스에만 기본 메소드를 제공할 수 있다.

    • 인터페이스를 상속받는 인터페이스에서 다시 추상 메소드로 변경할 수 있다.

    • 인터페이스 구현체가 재정의 할 수도 있다.

 

  • 스태틱 메소드
    • 해당 타입 관련 헬퍼 또는 유틸리티 메소드를 제공할 때 인터페이스에 스태틱 메소드를 제공할 수 있다.

 

 

2. 자바 8 API의 기본 메소드와 스태틱 메소드

  • Iterable의 기본 메소드
    • forEach()

    • spliterator()

 

forEach() : 각각의 요소들을 매개변수 삼아 동작한다. 밑의 예제에선 주석처리된 부분과 동일한 기능을 한다.

import java.util.ArrayList;
import java.util.List;

public class Practice {
    public static void main(String[] args) {
        List<String> names  = new ArrayList<>();
        names.add("kim");
        names.add("lee");
        names.add( "park");
        names.add( "jang");


        names.forEach(System.out::println);

//         for (String name : names) {
//         System.out.println(name)
//         }
    }
}

실행결과

kim
lee
park
jang

 

 

spliterator() : 각 요소를 쪼갠다. 여러 번 사용시 해당 회수만큼의 덩어리로 나눈다. 순서는 좀 섞이는 듯하므로 주의해야 할 것 같다.

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;

public class Practice {
    public static void main(String[] args) {
        List<String> names  = new ArrayList<>();
        names.add("kim");
        names.add("lee");
        names.add( "park");
        names.add( "jang");


        Spliterator<String> spliterator = names.spliterator();
        while (spliterator.tryAdvance(System.out::println));
    }
}

실행결과

kim
lee
park
jang

 

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;

public class Practice {
    public static void main(String[] args) {
        List<String> names  = new ArrayList<>();
        names.add("kim");
        names.add("lee");
        names.add( "park");
        names.add( "jang");


        Spliterator<String> spliterator = names.spliterator();
        Spliterator<String> spliterator1 = spliterator.trySplit();
        Spliterator<String>  spliterator2 = spliterator1.trySplit();

        while (spliterator.tryAdvance(System.out::println));
        System.out.println("============");
        while (spliterator1.tryAdvance(System.out::println));
        System.out.println("============");
        while (spliterator2.tryAdvance(System.out::println));
    }
}

실행결과

park
jang
============
lee
============
kim

 

  • Collection의 기본 메소드
    • stream() / parallelStream()

    • removeIf(Predicate)

    • spliterator()

stream() / parallelStream() : 요소들을 stream으로 만들어 어떤 처리를 할 수 있는 기능을 만듦. 다양하게 사용되고 자주 사용되므로 따로 다룬다.

 

removeIf(Predicate) : Predicate에 해당하는 요소를 뺀다.

import java.util.ArrayList;
import java.util.List;

public class Practice {
    public static void main(String[] args) {
        List<String> names  = new ArrayList<>();
        names.add("kim");
        names.add("lee");
        names.add("park");
        names.add("jang");


        names.removeIf(s -> s.startsWith("l"));

        names.forEach(System.out::println);
    }
}

실행결과

kim
park
jang

 

  • Comparator의 기본 메소드 및 스태틱 메소드
    • reversed()

    • thenComparing()

    • static reverseOrder() / naturalOrder()

    • static nullsFirst() / nullsLast()

    • static comparing()

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Practice {
    public static void main(String[] args) {
        List<String> names  = new ArrayList<>();
        names.add("kim");
        names.add("lee");
        names.add("park");
        names.add("jang");

        names.sort(String::compareToIgnoreCase);
        names.forEach(System.out::println);
        
        System.out.println("=========");

        Comparator<String> compareToIgnoreCase = String::compareToIgnoreCase;
        names.sort(compareToIgnoreCase.reversed());
        names.forEach(System.out::println);
    }
}

실행결과