Java 8이 나타나기 시작하여 기능 프로그래밍에 Lambda Expression (JSR-335)을 사용합니다. 오늘 우리는 수비수 방법으로도 알려진 Lambda : Virtual Extension의 일부에 대해 논의 할 것입니다. 이 기능을 사용하면 인터페이스 정의에서 메소드를 제공하는 방법을 구현할 수 있습니다. 예를 들어, 기존 인터페이스 (예 : 목록 및 맵)에 대한 메소드를 정의하여 다른 개발자 가이 메소드를 다시 구현할 필요가 없지만 실제로는 인터페이스입니다. 물론 Java 8은 이론적으로 기존 라이브러리와 호환됩니다.
가상 확장 방법은 Java에 여러 상속 특성을 제공하지만 가상 확장 방법은 행동 상속에 대해 제한됩니다. 아마도이 기능을 통해 여러 상속의 그림자를 볼 수 있습니다. 그러나 여전히 인스턴스 상태의 상속을 시뮬레이션 할 수 있습니다. 다음 기사에서 Mixin을 통해 국가의 상속을 설명하겠습니다.
Mixin에서 무엇이 혼합되어 있습니까?
믹싱은 주로 여러 서비스를 컨텍스트에 추가하는 데 사용됩니다. 예를 들어, "말"을 나타내는 수업이있는 경우,이 수업을 인스턴스화하여 "말"의 예를 만들 수 있습니다.
Val Myhouse = 정원이있는 차고가있는 새 집
Mixin 상속에서 특정 사양이 아니며, 이는 기존 범주에 다양한 기능을 추가하는 데 사용되는 방법 일뿐입니다. OOP에서는 Mixin과 함께, 당신은 그것을 통해 수업의 가독성이 있습니다.
예를 들어, Python의 SocketServer 모듈에 Mixin 방법이 있습니다. Mixin은 다중 프로세스를 지원하는 UDP 및 TCP 서비스를 포함한 4 개의 서비스와 다중 스레딩을 지원하는 UDP 및 TCP 서비스를 포함합니다.
클래스 포킹 프레스버 (Forkingmixin, Udpserver) : PassClass ForkingtCpserver (ForkingMixin, Tcpserver) : Pass Class ThreadingUdPserver (ThreadMixin) : PassClass ThreadingTcpserver (ThreadingMixin, TCPServer) : Pass
가상 확장 방법은 무엇입니까?
Java 8은 공개 수비수 방법이라고도하는 가상 확장 개념을 소개합니다.
VEM은 Java 인터페이스의 기본 메소드를 제공하는 것을 목표로합니다. 최대 절전 모드와 같은 세 번째 파티 라이브러리는 기본 메소드를 제공했기 때문에 이러한 수집 API의 모든 방법을 반복 할 필요는 없습니다.
다음은 인터페이스에서 메소드를 정의하는 방법의 예입니다.
공개 인터페이스 컬렉션 <T>는 반복 가능한 <T> {<R> Collection <R> 필터 (Prescticate <T> P) 기본값 {return Collection (this, p);}}}.
Java 8의 혼합 시뮬레이션
이제 우리는 VEM을 통해 혼합 효과를 달성하기 위해 왔지만 미리 경고는 다음과 같습니다. 직장에서 사용하지 마십시오!
다음 구현은 스레드 금고가 아니며 메모리 누출 문제가있을 수 있습니다.이 문제는 해시 코드에 따라 다릅니다.
우선, 메소드 정의 (시뮬레이션 상태 Bean)의 정의를 정의하고 방법을 제공합니다.
공개 인터페이스 switchablemixin {boolean isactivated () default {return switchables.isActivated (this);} void setAtcivated (부울 활동) 결함 {switchables.setActivated (this, Activated);}}
그런 다음 인스턴스 및 상태 연관성을 저장하기 위해 맵 인스턴스가 포함 된 도구 클래스를 정의합니다.
공개 최종 클래스 스위치블 {switchablemixin, switchabledevicestate = new Hashmap <(); Activity;} public static void setActivated (switchablemixin 장치, 부울 활성화) {switchabledevicestate = switch_states.get (state == null) {new switcheablevicestate.put (Device, State); .Activated = activated;} 개인 정적 클래스 Switchabledevicestate {개인 부울 활성화;}}}
다음은 상태의 상속을 강조하는 사용 사례입니다.
개인 정적 클래스 장치 {} private static class devicea 확장 장치 구현 switchablemixin {} private static class devicb 확장 장치 Imp Leater switchablemixin {}
"완전히 다른 것"
위의 구현은 정상적인 것으로 보이지만 Oracle의 Java Language Architect Brian Goetz는 현재 구현이 작동 할 수 없다는 질문을했습니다 (스레드 안전 및 메모리 누출이 해결되었다고 가정)
인터페이스 가짜 브로운 미신 {static map <string> backingmap = collections (new Beakhashmap <getname () default {return backingmap.get (} default {backingmap. put (this, name);}} interface x는 runnable, gakebrokenmixin {} x makex () {system.println ( "x"); x x1; (); x1. "x1";
실행 후이 코드가 표시 될 것이라고 추측 할 수 있습니까?
의심의 해결책
언뜻보기 에이 구현 코드에는 아무런 문제가 없습니다. x는 하나의 메소드 만 포함하는 인터페이스입니다. GetName과 SetName에는 이미 기본 정의가 있지만 실행 가능한 인터페이스의 실행 메소드는 정의되지 않으므로 Lambda 표현식을 통해 x 인스턴스를 생성 할 수 있습니다. 실행 방법의 구현. 따라서 실행 후이 프로그램을 원하는 결과는 다음과 같습니다.
x1x2
getName 메소드의 호출을 삭제하면 실행 결과가 다음과 같습니다.
MyTest $ 1@30ae8764 MyTest $ 1@123acf34
이 두 줄은 makex 메소드의 실행이 두 가지 다른 인스턴스에서 비롯되며 현재 OpenJDK 8이 생성된다는 것을 보여줍니다 (여기서는 OpenJDK 8 24.0-B07을 사용합니다).
어쨌든, 현재 OpenJDK 8 은이 문제를 해결하기 위해 최종 Java 8 동작을 반영하지 않으므로 Javac 명령을 사용한 후에는 특수 매개 변수를 사용해야합니다.
x2x2
GetName 메소드를 호출하지 않으면 표시됩니다.
MyTest $ $ $ lambda $ 1@5506d4eamytest $ $ lambda $ 1@5506d4ea
각 호출 MAKEX 메소드는 컴파일 된 Java 클래스 파일의 디렉토리를 관찰하면 MyTestClass $ $ 1.class라는 파일이 없다는 것을 알게됩니다.
컴파일 동안 Lambda 표현은 실제로 번역 과정을 겪지 않았다. 이 명령어에는 런타임시 Labda 표현에 대한 필요한 메타 정보가 포함되어 있습니다. 메소드 이름, 입력 및 출력 유형 및 Bootstrap이라는 메소드를 포함합니다. 부트 스트랩 방법은이 방법을 수신하는 인스턴스를 정의하는 데 사용됩니다.
방금 질문으로 돌아가서 Lambda 표현식은 개인 정적 메소드로 바뀌 었습니다.
개인 정적 무효 Lambda $ 0 () {System.out.println ( "x");}
Javap 카운터 컴파일 장치와 함께 프라이버시 매개 변수를 사용 하고이 메소드를 볼 수있는 경우 -C 매개 변수를 사용하여보다 완전한 변환을 볼 수도 있습니다.
프로그램을 실행할 때 JVM은 Lambda Metafactory 메소드를 호출하여 호출 된 동기 지침을 설명합니다. 이 예에서, MAKEX가 처음으로 요구되면 Lambda Metafactory 메소드는 X 인스턴스를 Lambda $ 0 메소드에 동적으로 연결합니다 메모리에서 두 번째 호출 인스턴스는 처음과 동일합니다.
수리 했습니까? 해결책이 있습니까?
이 문제에 대한 직접 수리 나 해결책은 없습니다. Oracle의 Java 8 프로그램 기본값 -xdlambdatomethod이지만이 매개 변수는 JVM 사양의 일부가 아니기 때문에 다른 공급 업체와 JVM의 구현은 다릅니다. Lambda 표현의 경우, 당신이 기대할 수있는 유일한 것은 클래스에서 인터페이스 메소드를 구현하는 것입니다.
다른 방법
지금까지 Mixin의 모방은 Java 8과 호환 될 수는 없지만 여러 상속 및 임명을 통해 여러 서비스를 추가 할 수 있습니다. 이 방법은 가상 필드 패턴 (가상 필드 모드)입니다.
그러니 우리의 전환 가능성을 살펴보십시오.
인터페이스 switchable {boolean isactive ();
전환 가능한 인터페이스가 필요하며 전환 가능한 구현으로 돌아갈 수있는 추가 추상화 방법을 제공합니다. 통합 메소드에는 기본 정의가 포함되어 있습니다.
Public Interface Switchable View는 Switchable {Boolean isactive () {return getSwitchable ()} 기본값 (getSwitchable).
다음으로 완전한 전환 가능한 구현을 만듭니다.
공개 클래스 Switchableimpl은 전환 가능 {private boolean active;
이것은 가상 필드 모드의 예입니다.
공개 클래스 장치 {} 공공 클래스 Devicea는 SwitchableView를 구현합니다 switchable getSwitchable () {return switchable;}}
결론적으로
이 기사에서는 두 가지 방법을 사용하여 Java 8의 가상 확장 방법을 통해 여러 서비스를 추가합니다. 첫 번째 방법은 맵을 사용하여 인스턴스 상태를 저장합니다.이 메소드는 스레드 안전이 아니며 메모리 누출 문제가 있기 때문에 위험합니다. 또 다른 방법은 가상 필드 모드를 사용하여 초록 Getter를 통해 최종 구현 예제를 반환하는 것입니다. 두 번째 방법은 더 독립적이고 안전합니다.
가상 확장 방법은 Java의 새로운 기능입니다.