Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4 Weeks - [추상 클래스와 인터페이스, Optional orElse 차이] #63

Open
devjy39 opened this issue Sep 3, 2023 · 1 comment

Comments

@devjy39
Copy link
Member

devjy39 commented Sep 3, 2023

문제

  • 추상 클래스와 인터페이스의 차이를 java 8 전과 후로 비교하며 알아갔으면 좋겠습니다.
  • Optional 의 orElse 와 orElseGet의 큰 차이, 잘못 사용함으로 인해 생길 수 있는 문제

contents - 세부 내용

  • 추상 클래스와 인터페이스는 아주 많이 물어보는 주제입니다. 하지만 책을 읽고 나서 java 8 전과 후로도 다른 차이가 생겼다는 것을 알게되었고, 비교해서 설명할 수 있으면 좋을 것 같습니다.
  • Optional의 orElse와 orElseGet중 써야되는 상황이 분명하게 다르고 잘못 사용했을 때 문제점이 있습니다. 다같이 알고 갔으면 좋겠습니다.

참고

Optional, interface default method

@leetaggg
Copy link
Member

leetaggg commented Sep 8, 2023

  1. 추상 클래스와 인터페이스는 인스턴스화가 불가능하며, 추상 메서드를 가질 수 있다는 것이 공통점입니다.

추상 클래스는 구현부가 있는 일반 메서드와 구현부가 없는 추상 메서드를 모두 가질 수 있으며, 인스턴스 변수를 가질 수 있습니다. 추상 클래스는 extends를 통해 자식 클래스가 상속을 받을 수 있으며, 단일 상속만을 지원하여 하나의 추상 클래스만 상속 받을 수 있습니다. 상속 받은 자식 클래스는 추상 클래스의 추상 메서드를 구현해야하며, 추상 클래스의 인스턴스 또한 사용할 수 있습니다.

인터페이스는 자바 8 이전에는 구현부가 없는 추상 클래스만 가질 수 있었지만, 자바 8 이후 정적 메서드와 구현부가 있는 디폴트 메서드를 가질 수 있습니다. 하위 클래스는 디폴트 메서드를 구현하지 않아도 됩니다.

  1. orElse와 orElseGet 메서드를 보면 두 메서드 모두 value가 null일 경우 객체를 반환합니다.

    차이점은 orElse는 other 객체를 반환하고 orElseGet은 Supplier 함수형 인터페이스의 get을 통해 객체를 반환한다는 점입니다.

// orElse(T other)
public T orElse(T other) {
        return value != null ? value : other;
    }

// orElseGet(Supplier<? extends T> supplier)
public T orElseGet(Supplier<? extends T> supplier) {
        return value != null ? value : supplier.get();
    }

예를 들어 Car 객체를 ofNullable 메서드로 감싸 orElse와 orElseGet으로 Car 객체를 반환하는 코드입니다.

public static void main(String[] args) {
        Car car = new Car("Red", 12345);

				Car otherCar1 = Optional.ofNullable(car).orElse(anyCar());
        System.out.println(otherCar1);
        // 메서드 실행
        // Red 12345

        Car otherCar2 = Optional.ofNullable(car).orElseGet(() ->anyCar());
        System.out.println(otherCar2);
        // Red 12345

    }
    static private Car anyCar(){
        System.out.println("메서드 실행");
        return new Car("anyCar", 54321);
    }

아래는 Car 객체에 null 값을 넣은 경우입니다.

public static void main(String[] args) {
        Car car = new Car("Red", 12345);

				Car otherCar1 = Optional.ofNullable(car).orElse(anyCar());
        System.out.println(otherCar1);
        // 메서드 실행
        // anyCar 54321

        Car otherCar2 = Optional.ofNullable(car).orElseGet(() ->anyCar());
        System.out.println(otherCar2);
        // 메서드 실행
        // anyCar 54321

    }
    static private Car anyCar(){
        System.out.println("메서드 실행");
        return new Car("anyCar", 54321);
    }

orElse 일 때는 Optional.ofNullable로 생성된 Optional 객체가 null 여부에 관계없이 orElse의 매개변수 anyCar()가 호출되고, orElseGet은 null 여부에 따라 호출되는 것을 알 수 있습니다.

이러한 결과가 나오는 이유는 orElseGet의 인수인 함수형 인터페이스 Supplier가 게으름 특징을 가지고 있어 불필요한 연산을 막아 null이 아닌 경우 실행되지 않기 때문입니다.

앞선 결과를 통해 orElse는 null 여부와 관계없이 매개변수를 호출한다는 것을 알게 되었으며, orElse를 사용할 때 null 여부에 따라 추가 동작을 할 경우 의도치 않는 결과가 발생할 수 있다는 것을 알 수 있습니다. 따라서 null 여부에 따라 추가 동작을 할 때에는 orElseGet을 사용해야하며, 고정적인 값을 반환할 때에는 orElse를 사용해야합니다.

@devjy39 devjy39 closed this as completed Sep 8, 2023
@devjy39 devjy39 reopened this Dec 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants