Java에서 Lambda 표현식의 Lambda 문법과 역할 영역 해석
이 절은 제2장 개편으로 전 장은 모든 새로운 개념을 간단명료하게 지적하고 책의 나머지 부분은 이런 개념에 대해 기초 지식의 보충과 실천을 깊이 있게 연구할 것이다.
이 장에서는 Lambda 표현식의 기초 지식을 소개합니다.
앞말
이전 책의 결어를 이 장의 학습 내용의 시작으로 삼아 Lambda 표현식의 장점을 요약한다.
comparing(...)
의 세립도 방법이 표준이 된다Lambda 구문
앞에서 언급한 바와 같이 자바에서는 독립된 순수 함수를 설명할 수 없지만 Lambda의 출현은 독립 함수와 더욱 비슷한 실현 방식을 제공했다.Lambda 형식만 봐도 간략한 문법의 스크립트 언어에서 설명한 함수 높이와 비슷하다.
# CoffeeScript
eat = (x) ->
alert("#{x} has been eatten!")
아무튼 보기만 해도 그렇다.그렇다면 람다 표현식의 문법은 어떤 것일까?
p -> p.translate();
i -> new Point();
(a, b) -> return a + b;
() -> "Ha!";
(x, y, z) -> {
x += y;
y += z;
z += x;
}
화살표 왼쪽은 임의의 수량의 매개 변수를 수신하고 오른쪽은 표현식체로 필요한 행동을 설명합니다.일반적으로 컨텍스트의 정보가 컴파일러가 해당 유형을 추정할 수 없는 한 매개변수 유형을 명시적으로 지정할 필요가 없습니다.
(int x, int y) -> x + y;
매개변수는 final로 선언할 수도 있고 메모(@Nullable, etc.)를 추가할 수도 있습니다.표현식체 부분은 방법의 호출로 사용할 수 있다. 예를 들어
str.length()
등은 표현식일 수도 있고 가감승제 등, 즉'문구 Lambda'와'표현식 Lambda'라는 두 가지 형식일 수도 있다.또한 반환값에 대해서는 사용
return sth_to_return
;없으면 리턴하기;또는 되돌아오는 문장을 직접 쓰지 않는다.마지막으로 주의해야 할 것은 Lambda 표현식은throws 키워드를 사용하지 않고 발생할 수 있고 위로 던져야 할 이상을 설명하는 것을 허락하지 않는다는 것이다.
Lambda와 익명 내부 클래스
앞의 몇 편의 문장에서 흔히 Lambda와 익명 내부류를 얕은 비교와 비교를 하였는데, 지금 우리는 이 점에 대해 구체적이고 깊이 있게 분석할 것이다.
문법
먼저 문법 차원에서 Lambda 표현식은 때때로 익명 내부류의'문법 설탕'이라고 불리는데 이것은 양자 간에 문법이 번거롭고 간결한 뚜렷한 차이가 존재한다는 것을 나타낸다.
식별 문제 없음
그 다음은 표지성 문제이다. 우리는 자바에서 대상을 구분하기 위해 모든 대상(익명 내부 클래스의 실례)이 유일한 표지를 가지고 있고 대상에 의존하여 존재하는 행위(즉 우리가 말한 방법)도 이 표지와 관련이 있다는 것을 안다.
예:
String bar = "bar";
String foo = "foo";
System.out.println(bar.hashCode()); // => 97299
System.out.println(foo.hashCode()); // => 101574
그러나 Lambda 표현식에 있어 상황은 이렇게 밝지 않다. 구체적인 상황에 따라 Lambda 자체가 표지를 가지고 있을 수도 있고 없을 수도 있다.게다가 Lambda는 일종의 행위를 나타내고 순수 함수 추세이기 때문에 일반적인 상황에서 표지를 사용하여 구분할 필요가 없다.
역할 도메인 규칙
게다가 양자의 작용역 크기의 차이다.
익명 내부 클래스의 경우 클래스 내에서 부모 형식 (즉 함수 인터페이스) 의 이름을 그대로 사용할 수 있음을 알 수 있다.
Lambda는 할 수 없습니다.
Runnable 인터페이스를 사용하여 예를 들어 보겠습니다.
public interface LetsRun extends Runnable {
String aString = "Big brother is watching.";
}
new Thread(
new LetsRun() {
@Override
public void run() {
System.out.println(aString);
}
}).run();
분명히 익명 내부 클래스는 우리가 LetsRun이라는 함수식 인터페이스에서 설명한 aString을 그대로 사용할 수 있다.이 코드를 다 쓰면서 IDE는 익명 내부 클래스를 Lambda로 접을 수 있다는 힌트를 주었습니다. 이제 자동으로 접을 수 있도록 해 주십시오.
new Thread((LetsRun) () -> System.out.println(LetsRun.aString)).run();
이때 인쇄해야 할 내용도 자동으로 LetsRun.aString
되어 상기 특징을 증명했다. 즉, Lambda는 부모 유형의 이름에 직접 접근할 수 없다는 것이다.외부 변수에 대한 접근 (뒷책에서 이를'변수 포획'이라고 함) 은 익명 내부 클래스든 Lambda든 역외 변수에 대한 권한이 제한되어 있다.
익명 내부 클래스에서는 외부 양을 읽을 수 있지만 변수를 수정하는 경향은 허용되지 않습니다.
즉, 엄격한 제한 규정이 없으면 방문한 외부량은final로 성명되어야 한다.
// This is OK
String anotherString = "WAR IS PEACE / FREEDOM IS SLAVERY / IGNORANCE IS STRENGTH";
// Also OK
final String finalString = "Nineteen Eighty-Four";
new Thread(new LetsRun() {
@Override
public void run() {
System.out.println(aString + "
" + anotherString + "
" + finalString);
}
}).run();
만약 방법에서 anotherString 값을 수정하면 컴파일은 통과할 수 없습니다.마찬가지로 Lambda로 접으면 여전히 합법적입니다.
new Thread((LetsRun) ()
-> System.out.println(LetsRun.aString + "
" + anotherString + "
" + finalString)).run();
변수 포획에 관한 문제는 다음 소절의 중점 내용으로 당분간 깊이 연구하지 않겠다.Lambda 표현식을 정의할 때 매개변수 부분과 표현식 내의 이름은 필드의 이름을 일시적으로 차단합니다.
public class Foo {
String x, y;
BinaryOperator binaryOperator = (x, y) -> x.hashCode() + y.hashCode();
// ...
}
또한 Lambda는 문장 블록에 해당하기 때문에 표현식 체내에 외부와 같은 언어 환경을 가진다. 즉this와 슈퍼는 같은 의미를 가진다.
public class MySuperClass {
public static final String aString = "Father";
}
public class MyClass extends MySuperClass {
public static final String aString = "Son";
public void aMethod() {
new Thread((LetsRun) () -> {
System.out.println("--- Lambda ---");
System.out.println(super.aString);
System.out.println(this.aString);
}).run();
System.out.println("--- Outside ---");
System.out.println(super.aString);
System.out.println(this.aString);
}
}
실행 결과:
--- Lambda ---
Father
Son
--- Outside ---
Father
Son
Lambda는 자신을 인용할 수 없기 때문에 어색한 방식으로 자신을 호출할 수 있습니다.
intUnaryOperator = i -> i == 0 ? 1 : i * intUnaryOperator.applyAsInt(i - 1);
작은 매듭Lambda는 다음과 같은 상위 유형에서 이름을 상속하지 않습니다.
final
( )
모두 역할 영역에서 제외됩니다.Lambda 매개 변수와 표현식체의 국부 성명은 필드 이름을 차단할 수 있습니다.
Lambda의this와 슈퍼의 의미는 외부와 완전히 일치합니다.
익명 내부 클래스에서 외부 객체에 액세스하는 현재 인스턴스는 OuterClass를 사용해야 합니다.this, 매우 서투르다:
new Thread((LetsRun) () ->
System.out.println(Foo.this.getClass().toString())
).run();
Lambda로 귀속할 때 Lambda 변수가 초기화되지 않고 해당 함수식 인터페이스의 방법만 직접 호출할 수 있음을 주의해야 한다.이 장 코드:
Foo.java
import java.util.function.BinaryOperator;
public class Foo {
String x, y;
BinaryOperator binaryOperator = (x, y) -> x.hashCode() + y.hashCode();
public static void main(String[] args) {
String bar = "bar";
String foo = "foo";
System.out.println(bar.hashCode());
System.out.println(foo.hashCode());
new Thread((LetsRun) () -> System.out.println(LetsRun.aString)).run();
String anotherString = "WAR IS PEACE / FREEDOM IS SLAVERY / IGNORANCE IS STRENGTH";
final String finalString = "Nineteen Eighty-Four";
new Thread((LetsRun) () -> System.out.println(LetsRun.aString + "
" + anotherString + "
" + finalString)).run();
new MyClass().aMethod();
new Foo().accessOuterClassInAnnoymousInnerClass();
}
public void accessOuterClassInAnnoymousInnerClass() {
new Thread((LetsRun) () ->
System.out.println(Foo.this.getClass().toString())
).run();
}
}
LetsRun.java
public interface LetsRun extends Runnable {
String aString = "Big brother is watching.";
}
MyClass.java
import java.util.function.IntUnaryOperator;
public class MyClass extends MySuperClass {
public static final String aString = "Son";
IntUnaryOperator intUnaryOperator = null;
public void aMethod() {
new Thread((LetsRun) () -> {
System.out.println("--- Lambda ---");
System.out.println(super.aString);
System.out.println(this.aString);
}).run();
System.out.println("--- Outside ---");
System.out.println(super.aString);
System.out.println(this.aString);
}
public void factorial() {
intUnaryOperator = i -> i == 0 ? 1 : i * intUnaryOperator.applyAsInt(i - 1);
}
}
MySuperClass.java
public class MySuperClass {
public static final String aString = "Father";
}
실행 결과:
97299
101574
Big brother is watching.
Big brother is watching.
WAR IS PEACE / FREEDOM IS SLAVERY / IGNORANCE IS STRENGTH
Nineteen Eighty-Four
--- Lambda ---
Father
Son
--- Outside ---
Father
Son
class Foo
위에서 말한 것은 편집자가 여러분께 소개한 자바에서 Lambda 표현식의 Lambda 문법과 작용역 해석입니다. 여러분께 도움이 되었으면 합니다. 만약에 궁금한 것이 있으면 저에게 메시지를 남겨 주십시오. 편집자는 제때에 여러분에게 회답할 것입니다.여기에서도 저희 사이트에 대한 지지에 감사드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.