Java8 Lambda와 익명 클래스
Java8이 최근에 출시되었고 새로운 람다식이 정말 멋져 보이기 때문에 이것이 우리가 익숙했던 익명 클래스의 종말을 의미하는지 궁금합니다.
나는 이것에 대해 조금 연구 해 왔고 Lambda 표현식이 어떻게 분류를 수행하기 위해 Comparator의 익명 인스턴스를 가져 오는 데 사용되는 Collection의 정렬 방법과 같은 이러한 클래스를 체계적으로 대체하는지에 대한 멋진 예제를 찾았습니다.
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
이제 Lambda를 사용하여 수행 할 수 있습니다.
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
그리고 놀랍도록 간결하게 보입니다. 제 질문은 Lambda 대신 Java8에서 이러한 클래스를 계속 사용하는 이유가 있습니까?
편집하다
같은 질문이지만 반대 방향으로, Lambda는 단일 메서드 인터페이스에서만 사용할 수 있기 때문에 익명 클래스 대신 Lambda를 사용하는 이점은 무엇입니까?이 새로운 기능은 몇 가지 경우에만 사용되는 바로 가기입니까 아니면 정말 유용합니까?
AIC (익명 내부 클래스)를 사용하여 추상 클래스 또는 구체적인 클래스의 하위 클래스를 만들 수 있습니다. AIC는 상태 (필드) 추가를 포함하여 인터페이스의 구체적인 구현을 제공 할 수도 있습니다. AIC의 인스턴스는 this
메서드 본문에서 사용하여 참조 될 수 있으므로 추가 메서드를 호출 할 수 있고 시간이 지남에 따라 상태가 변경 될 수 있습니다. 이들 중 어느 것도 람다에 적용되지 않습니다.
AIC의 대부분의 용도는 단일 함수의 상태 비 저장 구현을 제공하는 것이기 때문에 람다 식으로 대체 할 수 있지만 람다를 사용할 수없는 AIC의 다른 용도가 있습니다. AIC는 여기에 있습니다.
최신 정보
AIC와 람다 식의 또 다른 차이점은 AIC가 새로운 범위를 도입한다는 것입니다. 즉, 이름은 AIC의 수퍼 클래스 및 인터페이스에서 확인되며 어휘 포함 환경에서 발생하는 이름을 숨길 수 있습니다. 람다의 경우 모든 이름이 어휘로 확인됩니다.
Lambda는 훌륭한 기능이지만 SAM 유형에서만 작동합니다. 즉, 단일 추상 메서드와 만 인터페이스합니다. 인터페이스에 둘 이상의 추상 메서드가 포함되면 즉시 실패합니다. 익명의 클래스가 유용 할 것입니다.
따라서 우리는 익명 클래스를 무시할 수 없습니다. 참고로, and에 sort()
대한 유형 선언을 건너 뛰어 메서드를 더 단순화 할 수 있습니다 .p1
p2
Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));
여기에서 메서드 참조를 사용할 수도 있습니다. 클래스에 compareByFirstName()
메소드 를 추가 Person
하고 다음을 사용하십시오.
Collections.sort(personList, Person::compareByFirstName);
또는에 대한 getter를 추가 firstName
하고 Comparator
from Comparator.comparing()
메서드를 직접 가져옵니다 .
Collections.sort(personList, Comparator.comparing(Person::getFirstName));
익명 클래스를 사용한 Lambda 성능
응용 프로그램이 시작되면 각 클래스 파일을로드하고 확인해야합니다.
익명 클래스는 주어진 클래스 또는 인터페이스에 대한 새 하위 유형으로 컴파일러에 의해 처리되므로 각각에 대해 새 클래스 파일이 생성됩니다.
Lambda는 바이트 코드 생성이 다르며 JDK7과 함께 제공되는 invokedynamic 명령어를 사용하여 더 효율적입니다.
Lambda의 경우이 명령어는 런타임까지 바이트 코드의 람다 표현식 번역을 지연하는 데 사용됩니다. (처음으로 지침이 호출 됨)
결과적으로 Lambda 표현식은 정적 메서드가됩니다 (런타임에 생성됨). (stateles 및 statefull 케이스에는 작은 차이가 있으며 생성 된 메소드 인수를 통해 해결됩니다.)
다음과 같은 차이점이 있습니다.
1) 구문
Lambda 표현식은 AIC (Anonymous Inner Class)에 비해 깔끔하게 보입니다.
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("in run");
}
};
Thread t = new Thread(r);
t.start();
}
//syntax of lambda expression
public static void main(String[] args) {
Runnable r = ()->{System.out.println("in run");};
Thread t = new Thread(r);
t.start();
}
2) 범위
익명의 내부 클래스는 클래스이며, 이는 내부 클래스 내부에 정의 된 변수의 범위가 있음을 의미합니다.
반면에 람다 식은 자체 범위가 아니라 둘러싸는 범위의 일부입니다.
Similar rule applies for super and this keyword when using inside anonymous inner class and lambda expression. In case of anonymous inner class this keyword refers to local scope and super keyword refers to the anonymous class’s super class. While in case of lambda expression this keyword refers to the object of the enclosing type and super will refer to the enclosing class’s super class.
//AIC
public static void main(String[] args) {
final int cnt = 0;
Runnable r = new Runnable() {
@Override
public void run() {
int cnt = 5;
System.out.println("in run" + cnt);
}
};
Thread t = new Thread(r);
t.start();
}
//Lambda
public static void main(String[] args) {
final int cnt = 0;
Runnable r = ()->{
int cnt = 5; //compilation error
System.out.println("in run"+cnt);};
Thread t = new Thread(r);
t.start();
}
3) Performance
At runtime anonymous inner classes require class loading, memory allocation and object initialization and invocation of a non-static method while lambda expression is pure compile time activity and don’t incur extra cost during runtime. So performance of lambda expression is better as compare to anonymous inner classes.**
**I do realize that this point is not entirely true . Please refer following question for details. Lambda vs anonymous inner class performance: reducing the load on the ClassLoader?
Lambda's in java 8 was introduced for functional programming. Where you can avoid boilerplate code. I came across this interesting article on lambda's.
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
It's advisable to use lambda functions for simple logics. If implementing complex logic using lambdas will be a overhead in debugging the code in case of issue.
Lets compare the difference in between Lambda Expression and Anonymous class.
1. Syntax
Anonymous class:
package com.onlyfullstack;
public class LambdaVsAnonymousClass {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Anonymous class");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
Lambda:
package com.onlyfullstack;
public class LambdaVsAnonymousClass {
public static void main(String[] args) {
Runnable runnable = () -> System.out.println("Lambda Expression");
Thread thread = new Thread(runnable);
thread.start();
}
}
2. Implementation
Anonymous class can be used to implement any interface with any number of abstract methods. Lambda Expression will only work with SAM(Single Abstract Method) types. That is interfaces with only a single abstract method which is also called as Functional Interface. It would fail as soon as your interface contains more than 1 abstract method.
3. Compilation
Anonymous class: Java creates two class files for LambdaVsAnonymousClass java file as LambdaVsAnonymousClass.class – contains the main program LambdaVsAnonymousClass$1.class – contains an anonymous class
Lambda Expression: With Lambda expression compiler will create only 1 class file as below.
So Java will create the new class file for each Anonymous class used.
4. Performance
Anonymous classes are processed by the compiler as a new subtype for the given class or interface so there will be generated a new class file for each anonymous class used. When the application is launched each class which is created for the Anonymous class will be loaded and verified. This process is quite a time consuming when you have a large number of anonymous class.
Lambda expressions Instead of generating direct bytecode for lambda (like proposed anonymous class syntactic sugar approach), compiler declares a recipe (via invokeDynamic instructions) and delegates the real construction approach to runtime.
So Lambda expressions are faster than the Anonymous classes as they are only executed when they are called.
For more information, please refer to below links :
https://onlyfullstack.blogspot.com/2019/02/lambda-vs-anonymous-class-in-java-8.html
https://onlyfullstack.blogspot.com/2019/02/how-lambda-internally-works-in-java-8.html
- lambda syntax does not require to write the obvious code that java can infer.
- By using
invoke dynamic
, lambda are not converted back to the anonymous classes during compile time (Java do not have to go through creating objects, just care about signature of the method, can bind to method without creating object - lambda put more emphasis on what we want to do instead what we have to do before we can do it
Anonymous class are there to stay because lambda is good for functions with single abstract methods but for all other cases anonymous inner classes are your saviour.
참고URL : https://stackoverflow.com/questions/22637900/java8-lambdas-vs-anonymous-classes
'IT박스' 카테고리의 다른 글
이벤트를 정의 할 때 "event"키워드가 필요한 이유는 무엇입니까? (0) | 2020.08.19 |
---|---|
메모장 ++에서 모든 문자열을 각 문자열에 포함 된 숫자로 바꾸는 방법은 무엇입니까? (0) | 2020.08.19 |
SQL Server 2008 데이터베이스를 강제로 오프라인으로 전환하는 방법 (0) | 2020.08.19 |
서버와 성공적으로 연결되었지만 사전 로그인 핸드 셰이크 중에 오류가 발생했습니다. (0) | 2020.08.19 |
C #에서 비동기 적으로 메서드를 호출하는 방법 (0) | 2020.08.19 |