효과적인 자바! 익명 클래스보다 Lambda 선호

이 새 장에서는 몇 가지 새로운 Java 기능, 람다 및 스트림에 대한 새 섹션을 소개합니다. 저는 람다의 열렬한 팬이며 이것이 Java 언어에 큰 도움이 되었다고 생각합니다. 저는 개발 과정에서 매일 람다를 사용하며 확실히 코드가 훨씬 더 명확해졌습니다.

람다 이전에는 단일 메서드를 사용하는 인터페이스와 추상 클래스가 함수 유형으로 사용되었습니다. 이러한 인스턴스의 구현은 익명의 내부 클래스를 통해 생성되고 Java 코드에서 일종의 기능적 프로그래밍을 허용합니다. 예를 살펴보겠습니다.

Collections.sort(words, new Comparator<String> () {
  public int compare(String s1, String s2) {
    return Integer.compare(s1.length(), s2.length());
  }
});

위의 내용은 솔직히 너무 나빠 보이지 않으며 객체 지향 코드 내에서 가끔 발생하는 함수 객체에 적절하게 제공됩니다. Java 8에 람다가 도입되면서 상황이 훨씬 깨끗해지고 사용하기 쉬워졌습니다. 람다가 우리를 위해 하는 일은 단일 메소드와 인터페이스가 특별한 대우를 받아야 한다는 것을 성문화하는 것입니다. 기능적 인터페이스라고 하는 이러한 인터페이스는 익명 클래스를 사용하여 위에서 작성한 것을 정의하는 지름길을 허용합니다.

Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length());

람다를 사용하기 위한 이 작은 변경으로도 기본적으로 모든 상용구 코드를 제거할 수 있습니다. lamba에 대한 매개변수가 유형을 선언하지 않는다는 것을 알 수 있습니다. 이는 람다가 이 상용구를 건너뛸 수 있는 유형 유추(예: 최신 Java 버전의 var 키워드)를 사용할 수 있기 때문입니다. 이것은 우리가 유형을 제공할 수 없다는 것을 말하는 것이 아니며 드문 경우에 컴파일러는 유형을 유추할 수 없습니다. 이러한 경우에만 컴파일러가 요구할 때 유형을 정의해야 합니다. 메서드 참조와 함께 비교기 생성 메서드를 사용하는 것과 같이 위의 내용을 더 짧게 작성할 수 있는 방법이 있습니다.

Collections.sort(words, comparingInt(String::length));

또는 List.sort 메서드를 사용하여 더 짧습니다(기본 메서드의 예).

words.sort(commparingInt(String::length));

코드를 줄이고 실제 논리에 더 집중할 수 있게 됨으로써 람다는 이전에는 실용적이지 않았던 기능적 프로그래밍을 사용할 수 있게 해줍니다.

이전 장에서 우리는 다음과 같은 Operation 열거형에 대해 논의했습니다.

public enum Operation {
  PLUS { public double apply(double x, double y) { return x + y;}},
  MINUS { public double apply(double x, double y) { return x - y; }},
  TIMES { public double apply(double x, double y) { return x * y; }},
  DIVIDE { public double apply(double x, double y) {  return x / y; }};

 public abstract double apply(double x, double y);
}

람다를 사용하여 이 코드를 단순화할 수 있습니다.

public enum Operation {
  PLUS((x,y) -> x + y),
  MINUS((x,y) -> x - y),
  TIMES((x,y) -> x * y),,
  DIVIDE((x,y) -> x / y),

  private final DoubleBinaryOperator operator;

  Operation(DoubleBinaryOperator operator) {
    this.operator = operator;
  }

  public double apply(double x, double y) {
    return operator.applyAsDouble(x, y);
  }
}

위의 예는 DoubleBinaryOperator 패키지의 여러 인터페이스 중 하나일 뿐인 java.util.function 클래스를 사용합니다. 이 클래스는 유용한 여러 인터페이스로 가득 차 있습니다. 이것은 특히 두 개의double 매개변수를 받고 다른 매개변수double를 반환합니다. 단일 메소드로 인터페이스를 생성한 다음 클래스에 @FunctionalInterface 주석을 추가하여 이와 같은 고유한 인터페이스를 생성할 수 있습니다. @Override 주석과 유사한 주석은 동작을 유도하지 않지만 이 클래스에 메서드가 하나만 있어야 하며 기능적 인터페이스 기대치를 충족하지 않으면 컴파일에 실패할 것이라는 컴파일러에 대한 표시일 뿐입니다.

그래서 익명 클래스는 더 이상 쓸모가 없으며 사용하지 않습니까? 좀 빠지는. 람다가 할 수 없는 익명 클래스가 할 수 있는 것은 둘 이상의 추상 메서드가 있는 확장 추상 클래스의 인터페이스를 구현하는 것입니다. 또한 Lambda는 this 키워드로 자신을 참조할 수 없습니다. 실제로 이러한 제한은 규칙이 아니라 예외인 것 같습니다.

Lambda는 개발자가 상용구에 덜 집중하고 논리에 집중할 수 있도록 하는 간결한 코드를 작성하는 데 매우 유용합니다. 어떤 동작을 구현하기 위해 익명의 내부 클래스에 도달하는 자신을 발견했다면 람다 사용을 고려하십시오. 종종 올바른 선택이 될 것이며 나중에 귀하와 귀하의 코드에서 작업하는 다른 개발자를 위해 훨씬 더 명확한 코드로 이어질 것입니다.

좋은 웹페이지 즐겨찾기