JAVA

13. 자바 8의 특징

ggomjiu 2025. 4. 17. 18:15

1. 람다 표현식(Lambda Expression)

: 메서드로 전달될 수 있는 익명 함수를 단순한 문법으로 표기한 것

 

2. 함수형 인터페이스(Functional Interface)

: 추상 메서드가 오직 하나인 인터페이스

-> 단일 추상 메서드를 가지는 인터페이스

- 여러 개의 Default 메소드와 Static 메소드가 있어도 함수형 인터페이스로 취급

@FunctionalInterface
public interface Math {

    public int Callc(int first, int secont);
}




public class Main {

    public static void main(String[] args) {
        Math plusLambda = ((first, secont) -> first + secont);
        System.out.println(plusLambda.Callc(4,2));


        Math minusLambda = new Math() {
            @Override
            public int Callc(int first, int secont) {
                return first - secont;
            }
        };
        System.out.println(minusLambda.Callc(4,2));
    }
}

 

3. 디폴트 메소드(Default Method)

: 인터페이스 내에서 구현이 가능한 메소드

- static 메소드도 추가로 구현이 가능함

- 이전 버전에서는 인터페이스 내에서 추상 메소드만을 선언할 수 있었지만, static, default 메소드를 구현할 수 있게 됨

 

4. 스트림(Stream)

: 컬렉션과 배열의 데이터 처리를 도와주는 기술

- 이전 버전에서는 데이터를 처리하는 방법은 for문, for-each문을 돌면서 데이터를 가공

- 간단한 경우라면 상관없지만, 로직이 복합한 경우

-> 코드 양이 많아져 로직이 섞이고 쉽게 이해를 할 수 없는 상황이 발생

- 이러한 문제점을 해결하기 위해서 나온 기술

- 병렬 처리가 가능함

 

5. 옵셔널(Optional)

: 존재할 수도 있지만, 안할 수도 있는 객체, 즉, null이 될 수도 있는 객체를 감싸고 있는 일종의 래퍼 클래스

- NullPointerException을 방지하기 위해서 null 대신으로 나온 클래스

- Optional을 사용하면 NullPointerException을 유발할 수 있는 Null을 직접 다루지 않아도 됨

 

1) 기본 사용법

- 제너릭을 제공하기 때문에 변수를 선언할 때, 명기한 타입 파라미터에 따라서 감쌀 수 있는 객체의 타입이 결정됨

- 변수 명은 클래스 이름을 사용하기도 하지만, "maybe"나 "opt"와 같은 접두어를 붙여서 사용하는 게 Optional 클래스를 명확히 나타냄

 

2) 객체 생성하기

  1. Optional<Member> maybeMember = Optional.empty(); 
    • null을 담고 있는 객체를 생성
    • 클래스 내부적으로 미리 생성해 놓은 싱글턴 인스턴스임
  2. Optional<Member> maybeMember = Optional.of(aMember);
    • null이 아닌 객체를 생성
    • null이 넘어올 경우, NPE을 던지기 때문에 주의
  3. Optional<Member> maybeMember = Optional.ofNullable(aMember);
    Optional<Member> maybeNotMember = Optional.ofNullable(null);
    • null인지 아닌지 모르는 객체를 생성할 때 사용
    • null을 넣어 생성한 경우, 앞의 empty()함수처럼 비어있는 객체가 생성됨

3) Optional이 담고 있는 객체에 접근하기

- Optional에 null을 가지고 있을 때 다르게 작동하는 함수들에 대해 서술

  • get()
    • 비어있는 Optional 객체에 대해서 NoSuchElementException을 던짐
  • orElse( T other )
    • 비어있는 Optional 객체에 대해서 넘어온 인자를 반환
    • other은 메서드 호출 전에 무조건 평가됨
    • 즉, Optional에 값이 있든 없든 other은 먼저 만들어짐
  • orElseGet( Supplier <? extends T> other)
    • 비어있는 Optional 객체에 대해서 넘어온 인자를 반환
    • Optional이 비어있을 때만 실행됨
  • orElseThrow(Supplier <? extends X> exceptionSupplier)
    • 비어있는 Optional 객체에 대해서, 넘어온 함수형 인자를 통해 생성된 예외를 던짐

4) Optional의 잘못된 사용

- Optional에는 객체가 null인지를 확인하는 isPresent()라는 메소드가 있음

-> null이면 false, null이 아니면 true를 출력

-> 해당 메소드를 사용하면 Optional을 사용하는 이유가 없음

int length = Optional.ofNullable(getText()).map(String::length).orElse(0);

- 이와 같이 코드를 짜도록 노력해야 함

 

6. JVM의 변화

- 원래 Permanent Generation Heap(PermG)에는 아래와 같은 정보가 저장되어 있었음

  • Class의 메타 데이터 (바이트 코드 포함)
  • Method의 메타 데이터
  • static 객체, static 상수
  • 상수화된 String Object
  • Class와 관련된 배열 객체 메타 데이터
  • JVM 내부적인 객체들과 JIT의 최적화 정보

=> Permanent Heap은 일정량의 데이터 공간을 필수적으로 가지고 있어야 했음

 

cf) 메타데이터

: 어떤 데이터가 무엇인지 설명해주는 정보

- EX) 사진 : 데이터, 찍은 날짜 : 메타데이터

 

- Class와 Method의 메타데이터와 여러 객체들이 증가함으로 메모리양이 저장 공간보다 늘어나 OOM(Out Of Memory Error)가 발생하는 문제점이 발생함

- JVM에서 PermG 부분이 삭제되고, Native Memory 부분에 Metaspace가 추가 됨

- 기존의 PermG에 있었던 데이터는 아래와 같이 변경됨

  • MetaSpace에 저장되는 데이터
    • Class의 메타데이터(바이트 코드도 포함)
    • Method의 메타데이터
    • Class와 관련된 배열 객체 메타데이터
    • JVM 내부적인 객체들과 JIT의 최적화 정보
  • Heap에 저장되는 데이터
    • static 객체, static 상수
    • 상수화된 String Object

- Heap에 저장되는 데이터는 GC의 대상이 될 수 있게 됨

- Native 영역은 OS 레벨에서 관리해 자동으로 크기를 조절함

=> 개발자가 메모리 영역 확보의 상한을 크게 인식할 필요가 없게 됨

 

cf) GC가 관리하는 메모리

- 자바는 new 키워드로 객체를 생성 -> Heap 메모리에 저장

- 개발자가 따로 free()로 해제하지 않고 이러한 객체를 GC가 정리해줌

  1. 참조가 끊긴 객체를 찾음 -> 어떤 객체가 더 이상 코드에서 사용되지 않음
  2. 쓸모없는 객체를 제거 -> 그 객체가 차지하고 있던 메모리를 해제