亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

為什么編譯時不檢查 lambda 返回類型?

為什么編譯時不檢查 lambda 返回類型?

揚帆大魚 2023-10-13 10:09:35
使用的方法引用具有返回類型Integer。String但在下面的示例中,不兼容是允許的。如何修復方法with聲明以獲得方法引用類型安全而無需手動轉換?import java.util.function.Function;public class MinimalExample {  static public class Builder<T> {    final Class<T> clazz;    Builder(Class<T> clazz) {      this.clazz = clazz;    }    static <T> Builder<T> of(Class<T> clazz) {      return new Builder<T>(clazz);    }    <R> Builder<T> with(Function<T, R> getter, R returnValue) {      return null; //TODO    }  }  static public interface MyInterface {    Integer getLength();  }  public static void main(String[] args) {// missing compiletimecheck is inaceptable:    Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");// compile time error OK:     Builder.of(MyInterface.class).with((Function<MyInterface, Integer> )MyInterface::getLength, "I am NOT an Integer");// The method with(Function<MinimalExample.MyInterface,R>, R) in the type MinimalExample.Builder<MinimalExample.MyInterface> is not applicable for the arguments (Function<MinimalExample.MyInterface,Integer>, String)  }}
查看完整描述

4 回答

?
子衿沉夜

TA貢獻1828條經驗 獲得超3個贊

在第一個示例中,和MyInterface::getLength分別幫助"I am NOT an Integer"解析通用參數T和。RMyInterfaceSerializable & Comparable<? extends Serializable & Comparable<?>>


// it compiles since String is a Serializable

Function<MyInterface, Serializable> function = MyInterface::getLength;

Builder.of(MyInterface.class).with(function, "I am NOT an Integer");

MyInterface::getLength并不總是 a ,Function<MyInterface, Integer>除非您明確這么說,這會導致編譯時錯誤,如第二個示例所示。


// it doesn't compile since String isn't an Integer

Function<MyInterface, Integer> function = MyInterface::getLength;

Builder.of(MyInterface.class).with(function, "I am NOT an Integer");


查看完整回答
反對 回復 2023-10-13
?
翻過高山走不出你

TA貢獻1875條經驗 獲得超3個贊

類型推斷在這里發揮了作用。R考慮方法簽名中的泛型:

<R> Builder<T> with(Function<T, R> getter, R returnValue)

在所列情況中:

Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");

的類型R被成功推斷為

Serializable, Comparable<? extends Serializable & Comparable<?>>

并且 aString確實通過這種類型暗示,因此編譯成功。


要顯式指定 的類型R并找出不兼容性,只需將代碼行更改為:

Builder.of(MyInterface.class).<Integer>with(MyInterface::getLength, "not valid");


查看完整回答
反對 回復 2023-10-13
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

這是因為你的泛型類型參數R可以被推斷為 Object,即以下編譯:

Builder.of(MyInterface.class).with((Function<MyInterface, Object>) MyInterface::getLength, "I am NOT an Integer");


查看完整回答
反對 回復 2023-10-13
?
夢里花落0921

TA貢獻1772條經驗 獲得超6個贊

這個答案基于其他答案,這些答案解釋了為什么它不能按預期工作。


解決方案

下面的代碼通過將雙函數“with”拆分為兩個連貫函數“with”和“returning”來解決該問題:


class Builder<T> {

...

class BuilderMethod<R> {

  final Function<T, R> getter;


  BuilderMethod(Function<T, R> getter) {

    this.getter = getter;

  }


  Builder<T> returning(R returnValue) {

    return Builder.this.with(getter, returnValue);

  }

}


<R> BuilderMethod<R> with(Function<T, R> getter) {

  return new BuilderMethod<>(getter);

}

...

}


MyInterface z = Builder.of(MyInterface.class).with(MyInterface::getLength).returning(1L).with(MyInterface::getNullLength).returning(null).build();

System.out.println("length:" + z.getLength());


// YIPPIE COMPILATION ERRROR:

// The method returning(Long) in the type BuilderExample.Builder<BuilderExample.MyInterface>.BuilderMethod<Long> is not applicable for the arguments (String)

MyInterface zz = Builder.of(MyInterface.class).with(MyInterface::getLength).returning("NOT A NUMBER").build();

System.out.println("length:" + zz.getLength());

(有點陌生)


查看完整回答
反對 回復 2023-10-13
  • 4 回答
  • 0 關注
  • 175 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號