Java 8 (Spider)

2020. 11. 27. 17:01programming

2014.03월, 자바가 오라클에 인수되고 나온 첫 번째 버전으로 출시됨. 언어적으로 가장 역대급 변경이 아닌가 싶다.

 

1. Lambda Expression

- 원래는 java 7에서 도입 예정이었으나, 준비 부족으로 인해 제외하고 출시되었고, 이 버전에서 포함.

- 자바는 타입과 인터페이스에 대한 규약으로 인해, 간단한 인터페이스조차도 반드시 해당 타입을 구현하고 실행. → 많은 클래스와 실제 비즈니스보다 복잡한 코드를 양산.

- Functional Interface (추상 메서드 선언이 1개인 interface)는 메서드의 Meta 정보가 단일하기 때문에, 프로그램이 정확한 유추가 가능하다.

import org.junit.Test;

// 간단한 Thread 실행
public class LambdaTest {
  @Test
  public void testLambdaExpress() {
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("New Thread Start!");
      }
    }).start();
  }
}

위 예제는 아주 익숙한 Thread 실행 코드다. Thread의 생성자는 Runnable 타입의 interface를 인자로 받는데, 여기서는 익명 내부 클래스로 구현을 했다. 이렇게 한 번 쓰이는 로직조차도, 반드시 인터페이스의 규약을 지켜야 하며, 이 인터페이스의 구현이 공유되어야 한다면, 별도 클래스로 분리 구현한다.

 

여기서 Runnable interface를 살펴보면, 이것이 Functional interface 임을 알 수 있다.(추상 메서드가 run 하나다.) 따라서, 컴파일러는 다음을 유추할 수 있다.

1) 해당 자리에 오는 인자는 Runnable interface 다.

2) 해당 자리에는 run 메서드가 실행될 것이다.

3) run 메서드는 인자와 반환값이 없다.

자, 이제 이 내용은 이미 간파당했으므로, 다음과 같이 생략이 가능하다.

import org.junit.Test;

// 간단한 Thread 실행 2
public class LambdaTest {
  @Test
  public void testLambdaExpress() {
    new Thread(() -> {
      System.out.println("New Thread Start!");
    }).start();;
  }
}

Runnable interface는 간파당했으므로 생략. 유일한 메서드 run은 이름이 알려졌으므로 생략. 메서드의 인자는 없으므로 괄호만 남는다. () 부분. 이것이 -> 기호를 통해 본문으로 이어지며, 실제 비즈니스를 블록으로 표현하는 부분만 남았다. 위와 같이 단일 라인이라면, 블록과 세미콜론을 생략 가능하다.

당연히, custom 하게 작성된 Functional interface에도 적용된다.

 

※ @FunctionalInterface

// Functional interface 선언
public interface FunctionalIf {
  public String hello(String name);
}

// Functional interface를 사용과 람다식을 이용한 선언 즉시 구현
import org.junit.Test;

public class LambdaTest {
  @Test
  public void testLambdaExpress() {
    FunctionalIf add = (name) -> name + ", Hello!";
    
    System.out.println(add.hello("Tom"));
  }
}

FunctionalIf는 유추 가능한 것을 생략하고 람다식을 이용해 표현하였다. 물론 (name) -> { return name + ",hello!"; }; 와 같이 정확한 블록 구문으로 표현 가능하지만, 앞서 보았듯이 단일 문장은 생략 가능하다.

 

그런데, 저렇게 쓰고 있는 와중에, 누군가 FunctionalIf에 추상메소드 선언을 추가한다면? 바로 그 인터페이스를 람다식으로 쓰고 있는 아래의 코드가 깨지게 된다. 왜냐하면, 더 이상 Functional Interface 형태가 아니기 때문이다. 따라서, FunctionalIf를 다음과 같이 선언하면,

@FuncationalInterface
public interface FunctionalIf {
  public String hello(String name);
}

해당 interface는 @FunctionalInterface annotation으로 인해, 추상 메서드를 추가할 수 없다. (컴파일 시 Functional Interface의 형식 검증을 받는다.)

 

 

2. Stream API

- 람다 표현식을 적극 활용하여, Collection 을 함수형으로 다루는 방식을 소개

- Collection은 자료구조가 포함하는 모든 값을 메모리에 놓고 연산하나, Stream은 요청하는 값만 Stream으로 추출 연산 > 늦은 초기화 > 1회 성 연산 구조를 가진다. (반복 사용 불가)

- .parallel 을 통한 쉬운 병렬 처리 지원

// 기본 Stream 구조
import java.util.Arrays;
import org.junit.Test;

public class StreamTest {
  @Test
  public void testStream() {
    Arrays.asList(1,2,3,4,5).stream()  //Stream생성
    .filter(i -> i > 2)                //중간연산 java.util.stream.Stream.filter(Predicate<? super Integer> predicate)
    .map(i -> i+1)                     //중간연산 java.util.stream.Stream.map(Function<? super Integer, ? extends Integer> mapper)
    .forEach(System.out::println);    //최종연산 java.util.stream.Stream.forEach(Consumer<? super Integer> action)
  }
}

여기서는 간단하게 Stream의 구조만 살펴보면, 기본적으로 stream 생성 > 중간 연산 > 최종 연산의 구조를 이룬다.

람다식을 이용한 중간 연산, 최종 연산 부분에 대한 이해는, 람다식이 Functional Interface의 유추 가능한 부분은 모두 생략한다는 점을 상기하고 보면 이해가 쉽다.

· filter : stream의 요소를 비교하고, 비교문을 만족하는 stream을 반환.

· map : stream의 개별 요소 연산.

· forEach : stream의 요소 반복문.

 

 

3. Default Method

- 자바의 interface는 메서드 선언이 추가되면, 구현 클래스는 모두 이를 구현하고 재컴파일 해야 함.

- 하위 호환성에 영향을 주지 않고, interface에 새로운 메서드를 추가할 수 있음.

- 기본 구현을 가지기 때문에 추상 메서드가 아님.

- 람다식은 Functional Interface의 전제 조건 때문에, 이 개념이 추가된 것으로 보임.

- 그럼, 다시 다중 상속의 문제는? (A, B interface의 동일 default 메서드 정의, 하나의 클래스에서 동시 구현하는 경우 어떤 default 메서드 인가?) 하나를 얻고, 하나를 잃은 건가. 장점으로 내세울 땐 언제고, 이젠 C++의 다중 상속 회피 방식을 따르게 된다. 아이러니하고만.

 

4. JavaFX

- 원래 JavaFX는 Flash에 대적하기 위한 기술.

- Flash에 밀리고, 그 Flash가 HTML5에 밀린 작금의 상황에서, JavaFX는 Swing을 대체하는 자바의 대표 GUI로써 소개됨.

 

5. Nashorn

- embeded javascript runtime engine

- 기존의 모질라 자바스크립트 엔진(Rhino)에 비해 월등한 성능 향상 제공.

 

6. New Date API

- Joda Time을 참고한 새로운 날짜 API 제공.

- LocalDate, LocalTime, LocalDateTime, ZonedDateTime, OffSetDateTime, OffSetTime 등

 

7. 기타

- 중복 annotation 허용

- annotation에 사용된 매개변수의 자동 대응 (@RequestParam("name") String name > @RequestParam String name 등)

- JVM 메모리 영역의 Permenant Generation 영역 제거

(이 영역에 대한 문제는 아래 JVM 부분 참조)

 

JVM 이란

jvm은 간단히 얘기하면 java 실행 환경 이다. 이것을 아는 것은 왜 중요할까? 이는 jvm 이전의 프로그래밍 언어의 패러다임과 관련이 있다. 이전의 언어는 하드웨어를 직접 제어하기도, 메모리를 직

madep.tistory.com

'programming' 카테고리의 다른 글

java 버전별 특징(1.0~1.7)  (0) 2020.11.25
JVM 이란  (0) 2020.10.30
비트마스크  (0) 2020.10.19
객체지향 개발 원칙  (0) 2020.10.16