본문 바로가기
프로그래밍/Java

[Java 8] Java 8에서의 새로운 특징

by 사바라다 2019. 11. 19.

안녕하세요.이미 자바는 11버전을 향해 달리고 있지만 우리는 아직 낯선게 사실입니다. 우리뿐만 그런건 아닙니다. 아직 많은 오픈소스에서  호환되지 않기도 하지요. 언젠간 11버전에 대해서도 알아보겠지만 일단 요즘 대부분의 표준이 되고 있는 Java 8 버전에 대해서 이전 버전들과의 차이점에 대해 알아보도록 하겠습니다.

Interface의 변화

Java 8 버전이전에는 interface는 public abstract methods만 허용했습니다. 하지만 Java 8 부터는 interface에서 static과 default 메서드를 사용할 수 있습니다.

static method

public interface Vehicle {
    void run();
    static String producer() {
        return "Hyundai Vehicles";
    }
}

이렇게 static 메서드를 구현하여 사용할 수 있습니다. Client에서는 아래와 같이 사용할 수 있습니다.

String producer = Vehicle.producer();

Default Method

Default 메서드는 default 키워드를 선언하여 사용할 수 있습니다. default로 선언된 메서드는 그냥 사용할 수도 있으며 override하여 사용할 수도 있습니다.

public interface Vehicle {
    void run();
    default String producer() {
        return "Hyundai Vehicles";
    }
}

이렇게 선언하며 아래와 같이 사용할 수 있습니다.

Vehicle vehicle = new VehicleImpl();
String producer = vehicle.producer(); // expeced Hyndai Vehicles

 

Interface에 static과 default method가 추가됨으로써 기존의 abstract class에서 interface를 구현해서 default method를 만들어내는 방법을 사용하지 않아도 되게됬습니다.

메서드 참조

예제 Class

public class User {

    private String name;

    public User(String name) {
        this.name = name;
    }

    public static boolean isRealUser(User user) {
        ...
    }
}

static

lambda식에서 사용하는 메서드 참조는 더 짧고 가독성 있게 사용할 수 있도록 되었습니다. static 메서드라고 하면 ContainingClass::methodName의 형식으로 사용할 수 있습니다.

List<User> list = Arrays.asList(new User("Kim"), new User("Yeom"))
list.stream.anyMatch(u -> User.isRealUser(u));

위의 뜻은 list에서 한개의 요소를 탐색해가며 isRealUser라는 메서드가 만족하는지 보는 것입니다. 이러한 식은 아래와 같이 변경할 수 있습니다.

list.stream.anyMatch(User::isRealUser);

instance type

static 메서드가 아니라고 하더라도 가능합니다. 위 예제의 isRealName 메서드가 User class의 메서드가 되었다고 했을 때 아래와 같이 가능한 것입니다..

User user = new User("Kim");
list.stream().anyMatch(user::isRealName);

생성자

ClassName::new의 형식으로 생성자를 나타낼 수 있습니다.

List<String> list = Arrays.asList("Kim", "Yeom");
list.stream.map(User::new);

위와 같이 처리한다면 Kim과 Yeom에 대한 User가 map을 통해 만들어 질 것입니다.

Optional

Optional class는 Java 8에서 등장하여 NullPointerException의 발생가능성에 대한 코드에대해 도와줄 수 있습니다.

예제 1

List<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();

이런코드가 있다고 하겠습니다. 이 코드는 getList에서 받아온 list가 null이라면 새로 인스턴스를 할당한다는 것입니다. 이러한 코드를 Optional을 이용하면 아래와 같이 변합니다.

List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());

간결해 진것을 알 수 있습니다.

예제 2

좀 더 와닿는 예제를 보도록 하겠습니다.

User user = getUser();
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        String street = address.getStreet();
        if (street != null) {
            return street;
        }
    }
}
return "not specified";

이런 예제가 있습니다. user가 null인지 먼저 체크한 후 차례대로 address를 체크, street를 체크합니다. 코딩을 하다보면 위와같은 상황은 자주 마주치게 됩니다. 위 예제를 Optional을 사용하여 변경해보겠습니다.

Optional<User> user = Optional.ofNullable(getUser());
String result = user
  .map(User::getAddress)
  .map(Address::getStreet)
  .orElse("not specified");

2줄로 처리할 수 있도록 변경되었습니다.

마무리

이렇듯 java8에서는 우리가 불편하게 중복하여 사용하던 부분을 간략하게 사용할 수 있도록 많이 진화하였습니다. java8을 잘 사용한다면 코딩이 보다 쉽고 간결해 질 것입니다. 다음시간에는 Stream에 대해서 알아보도록 하겠습니다.

참조

https://www.baeldung.com/java-8-new-features

댓글