기본 방법이있는 이유는 무엇입니까?
Java 8이 다가오고 있지만 출시 기간이 연기되었지만 Lambdas 표현이 최종적으로 석방 될 때 지원 될 것이라고 확신합니다. 앞에서 언급했듯이, 우리는 이전 에이 주제에 대해 많은 것을 논의했지만 Lambdas 표현은 Java 8에서 게임 규칙의 유일한 변화는 아닙니다.
Java 8이 출시되어 Lambda를 포함한다고 가정합니다. 이제 Lambda를 사용할 계획입니다.
list <?> list = ... list.faceach (…);
Foreach의 정의는 java.util.list 또는 java.util.collection에서 찾을 수 없습니다. 일반적으로 JDK의 관련 인터페이스에 새로운 방법과 구현을 추가하는 솔루션입니다. 그러나 릴리스 릴리스의 경우 기존 구현에 영향을 미치지 않고 인터페이스에 새로운 메소드를 추가하는 것은 불가능합니다.
따라서 Lambda가 Java 8에서 사용되는 경우 전방 호환성으로 인해 컬렉션 라이브러리에 사용될 수 없습니다.
위의 이유로 새로운 개념이 소개되었습니다. 일반적으로 방어 방법 인 가상 확장 방법을 이제 인터페이스에 추가하여 문의 동작의 기본 구현을 제공 할 수 있습니다.
간단히 말해서 Java 인터페이스는 이제 메소드를 구현할 수 있습니다. 기본 메소드의 장점은 인터페이스의 구현을 파괴하지 않고 인터페이스에 새로운 기본 메소드를 추가 할 수 있다는 것입니다.
제 생각에는 이것은 매일 사용될 Java 특성의 종류는 아니지만 Lambda를 사용하여 자연스럽게 Lambda를 사용할 수 있습니다.
가장 간단한 예
가장 간단한 예를 보자 : 인터페이스 a, Clazz Class는 인터페이스를 구현합니다.
public interface a {default void foo () {system.out.println ( "calling a.foo ()";} public class class a {}Clazz 클래스가 foo () 메소드를 구현하지 않더라도 코드를 컴파일 할 수 있습니다. foo () 메소드의 기본 구현은 인터페이스 A에 제공됩니다.
이 예제를 사용한 클라이언트 코드 :
Clazz Clazz () Clazz.foo ();
다중 상속?
일반적인 질문이 있습니다. 사람들은 "클래스가 두 인터페이스를 구현하는 경우"기본 메소드의 새로운 기능을 처음들을 때 묻습니다 이전 예제와 함께 :
public interface a {default void foo () {system.out.println ( "Calling A.Foo ()"( "Calling B.Foo ()";}} 공개 클래스 클래스 A, B {}이 코드는 다음과 같은 이유를 컴파일 할 수 없습니다.
java : 유형 A에서 B 로의 클래스 클래스 (Class Clazz)는 관련없는 기본값을 상속합니다.
이를 수리하려면 Clazz에서는 갈등을 다시 작성하는 방법을 수동으로 해결해야합니다.
공개 클래스 클라즈는 A, B {public void foo () {}}} 그러나 자체 방법을 구현하는 대신 인터페이스 A에서 기본 구현 방법을 호출하려면 어떻게해야합니까? 이것은 다음과 같이 foo ()를 a로 인용 할 수 있습니다.
공개 클래스 클라즈는 a, b {public void foo () {a.super.foo ();}}} 이제 나는이 최종 솔루션을 좋아한다고 확신 할 수 없습니다. 기본 메소드 사양의 첫 번째 초안에 선언 된대로 서명에서 기본 메소드를 실현하는 것보다 더 간결 할 수 있습니다.
공개 클래스 클라즈는 A, B {public void foo () default A.Foo;}그러나 이것은 문법을 바꾸지 않습니까? 인터페이스 A와 인터페이스 B가 서로 충돌하는 많은 기본 메소드를 정의하고 충돌을 해결하기 위해 모든 인터페이스 A의 기본 메소드를 사용 하려는가? 현재, 나는 모든 갈등을 다시 작성하기 위해 갈등을 해결해야합니다. 이를 위해서는 많은 작업이 필요할 수 있으며 많은 템플릿 코드를 작성해야 할 수도 있습니다.
나는 갈등을 해결하는 방법에 많은 토론이 필요하다고 추정하지만, 제작자는 피할 수없는 재난을 받아들이기로 결정한 것으로 보인다.
실제 예
기본 방법의 실제 예는 JDK8의 초기 백에서 찾을 수 있습니다. 컬렉션의 컬렉션 방법의 예로 돌아가서 Java.lang.tertable 인터페이스에서 기본 구현이 다음과 같습니다.
@functionalInterFacePublic interface iterable <t> {iterator <t> iterator (); Foreach는 java.util.function.consumer function 인터페이스 유형의 매개 변수를 사용하여 다음과 같이 Lambda 표현식 또는 메소드 참조를 전달할 수 있습니다.
list <?> list = ... list.faceach (system.out :: println);
방법 호출
기본 메소드가 실제로 어떻게 호출되는지 살펴 보겠습니다. 이 문제에 익숙하지 않다면 Java 바이트에 대한 Rebel Labs를 읽는 데 관심이있을 수 있습니다.
클라이언트 코드의 관점에서 기본 메소드는 일반적인 가상 메소드 일뿐입니다. 따라서 이름은 가상 확장 방법이어야합니다. 따라서 인터페이스로 기본 메소드의 간단한 예제를 위해 클라이언트 코드는 기본 메소드가 호출되는 위치에서 인터페이스를 자동으로 호출합니다.
Clazz = Clazz.foo ();
기본 메소드의 충돌이 해결되면 기본 메소드를 수정하고 인터페이스 중 하나를 지정하면 InvokEspecial은 특정 호출의 인터페이스 구현을 구현할 것입니다.
Public Class Clazz는 A, B {public void foo () {a.super.foo (); 다음은 Javap의 출력입니다.
public void foo (); 코드 : 0 : aload_01 : interfacemethod a.foo : / () v4 : return : return
보시다시피 : Invokespecial 지침은 인터페이스 메소드 foo ()를 호출하는 데 사용됩니다. 바이트 코드의 관점에서 볼 때, 이것은 여전히 새로운 것입니다. 왜냐하면 인터페이스를 가리키는 슈퍼 대신 클래스 (부모)를 가리키면 메소드를 호출하기 전에는 여전히 새로운 것입니다.
마침내…
기본 방법은 Java 언어에 대한 흥미로운 보충제입니다. 기본 표현식의 주요 목표는 표준 JDK 인터페이스를 발전시키는 것입니다. 결국 Java 8의 Lambdas 표현식을 사용하기 시작하면 원활한 전환 경험을 제공합니다. 누가 아는 사람, 아마도 우리는 향후 API 디자인에서 더 많은 기본 방법을 볼 수있을 것입니다.