第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

LambdaMetaFactory 具有泛型類型的具體實現(xiàn)

LambdaMetaFactory 具有泛型類型的具體實現(xiàn)

慕慕森 2021-11-17 15:04:35
我試圖使用Java的LambdaMetaFactory動態(tài)實現(xiàn)一個通用的拉姆達Handler<RoutingContext>:public class RoutingContext {    // ...}@FunctionalInterfacepublic interface Handler<X> {    public void handle(X arg);}public class HomeHandler extends Handler<RoutingContext> {    @Override    public void handle(RoutingContext ctx) {        // ...    }}這是我的嘗試LambdaMetaFactory:try {    Class<?> homeHandlerClass = HomeHandler.class;    Method method = homeHandlerClass.getDeclaredMethod(            "handle", RoutingContext.class);    Lookup lookup = MethodHandles.lookup();    MethodHandle mh = lookup.unreflect(method);    MethodType factoryMethodType = MethodType.methodType(Handler.class);    MethodType functionMethodType = mh.type();    MethodHandle implementationMethodHandle = mh;            .getTarget()            .invokeExact();    lambda.handle(ctx);} 這給出了錯誤:java.lang.AbstractMethodError: Receiver class [...]$$Lambda$82/0x00000008001fa840does not define or inherit an implementation of the resolved method abstracthandle(Ljava/lang/Object;)V of interface io.vertx.core.Handler.我已經(jīng)為functionMethodTypeand嘗試了一系列其他選項implementationMethodHandle,但還沒有設(shè)法讓它工作。此外,即使我將RoutingContext.class引用替換為Object.class,也無法修復(fù)錯誤。我可以使lambda.handle(ctx)調(diào)用成功的唯一方法是更改HomeHandler以使其不擴展Handler、HomeHandler::handle靜態(tài)化并更改RoutingContext.class為Object.class. 奇怪的是,我仍然可以將生成的 lambda 轉(zhuǎn)換為Handler<RoutingContext>,即使它不再擴展Handler。我的問題:我如何開始LambdaMetaFactory使用非靜態(tài)方法?對于這個非靜態(tài) SAM 類HomeHandler,它如何在后臺處理實例分配?是否LambdaMetaFactory創(chuàng)建接口實現(xiàn)的單個實例,無論有多少方法調(diào)用,因為在此示例中沒有捕獲的變量?還是為每個方法調(diào)用創(chuàng)建一個新實例?或者我應(yīng)該創(chuàng)建一個實例并以某種方式將它傳遞給 API?我如何開始LambdaMetaFactory使用泛型方法?編輯:除了下面的好答案外,我還看到了這篇博文,解釋了所涉及的機制:https://medium.freecodecamp.org/a-faster-alternative-to-java-reflection-db6b1e48c33e
查看完整描述

2 回答

?
30秒到達戰(zhàn)場

TA貢獻1828條經(jīng)驗 獲得超6個贊

或者我應(yīng)該創(chuàng)建一個實例并以某種方式將它傳遞給 API?

是的。HomeHandler::handle是一個實例方法,這意味著您需要一個實例來創(chuàng)建功能接口包裝器,或者每次調(diào)用它時都傳遞一個實例(對于它Handler不能作為 FunctionalInterface 類型工作)。

要使用捕獲的實例,您應(yīng)該:

  • 更改factoryMethodType為也采取HomeHandler實例

  • 更改functionMethodType為 SAM 的擦除類型,該類型以 anObject作為參數(shù)。

  • instantiatedMethodType參數(shù)更改為沒有捕獲HomeHandler實例的目標(biāo)方法句柄的類型(因為它已被捕獲,因此您不再需要它作為參數(shù))。

  • 創(chuàng)建功能接口接口時傳遞HomeHandlerto的實例invokeExact。

——

Class<?> homeHandlerClass = HomeHandler.class;


Method method = homeHandlerClass.getDeclaredMethod(

        "handle", RoutingContext.class);

Lookup lookup = MethodHandles.lookup();

MethodHandle mh = lookup.unreflect(method);


MethodType factoryMethodType = MethodType.methodType(Handler.class, HomeHandler.class);

MethodType functionMethodType = MethodType.methodType(void.class, Object.class);

MethodHandle implementationMethodHandle = mh;


Handler<RoutingContext> lambda =

        (Handler<RoutingContext>) LambdaMetafactory.metafactory(

                lookup,

                "handle",

                factoryMethodType, 

                functionMethodType,

                implementationMethodHandle,

                implementationMethodHandle.type().dropParameterTypes(0, 1)) 

        .getTarget()

        .invokeExact(new HomeHandler()); // capturing instance

lambda.handle(ctx);

當(dāng)然,因為HomeHandlerimplements Handler,你可以直接使用捕獲的實例;


new HomeHandler().handle(ctx);

或者利用編譯器生成元工廠代碼,它也使用invokedynamic,這意味著CallSite返回的 byLambdaMetafactory.metafactory只會被創(chuàng)建一次:


Handler<RoutingContext> lambda = new HomeHandler()::handle;

lambda.handle(ctx);

或者,如果功能接口類型是靜態(tài)知道的:


MethodHandle theHandle = ...

Object theInstance = ...

MethodHandle adapted = theHandle.bindTo(theInstance);

Handler<RoutingContext> lambda = ctxt -> {

    try {

        adapted.invokeExact(ctxt);

    } catch (Throwable e) {

        throw new RuntimeException(e);

    }

};

lambda.handle(new RoutingContext());


查看完整回答
反對 回復(fù) 2021-11-17
?
BIG陽

TA貢獻1859條經(jīng)驗 獲得超6個贊

既然你說“很遺憾 LambdaMetaFactory API 如此復(fù)雜”,那么應(yīng)該提到它可以做得更簡單。


首先,在使用時LambdaMetaFactory,直接使用它:


Lookup lookup = MethodHandles.lookup();

MethodType fType = MethodType.methodType(void.class, RoutingContext.class);

MethodHandle mh = lookup.findVirtual(HomeHandler.class, "handle", fType);


Handler<RoutingContext> lambda = (Handler<RoutingContext>) LambdaMetafactory.metafactory(

    lookup, "handle", MethodType.methodType(Handler.class, HomeHandler.class),

    fType.erase(), mh, fType).getTarget().invokeExact(new HomeHandler());

您將使用綁定接收器調(diào)用實例方法,并且不包括接收器的目標(biāo)方法的類型與instantiatedMethodType參數(shù)相同。此外,由于Tin的邊界Handler<T>是Object,您可以簡單地使用erase()該方法類型來獲取samMethodType參數(shù)的擦除簽名。


它并不總是那么簡單。考慮將方法綁定static int method(int x)到Consumer<Integer>. 那么,samMethodType參數(shù)是(Object)void,instantiatedMethodType參數(shù)是(Integer)void,而目標(biāo)方法的簽名是int(int)。您需要所有這些參數(shù)來正確描述要生成的代碼??紤]到其他(前三個)參數(shù)通常由 JVM 填充,這種方法已經(jīng)只需要必要的最小值。


其次,如果您不需要最高性能,則可以簡單地使用Proxy基于實現(xiàn)的實現(xiàn):


MethodHandle mh = MethodHandles.lookup().findVirtual(HomeHandler.class,

    "handle", MethodType.methodType(void.class, RoutingContext.class));

Handler<RoutingContext> lambda = MethodHandleProxies.asInterfaceInstance(

    Handler.class, mh.bindTo(new HomeHandler()));


查看完整回答
反對 回復(fù) 2021-11-17
  • 2 回答
  • 0 關(guān)注
  • 308 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號