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

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

Java編譯器:兩個同名不同簽名的方法如何匹配一個方法調用?

Java編譯器:兩個同名不同簽名的方法如何匹配一個方法調用?

慕虎7371278 2022-12-15 14:54:30
我有這個類稱為Container:public class Container {    private final Map<String, Object> map = new HashMap<>();    public void put(String name, Object value) {        map.put(name, value);    }    public Container with(String name, Object value) {        put(name, value);        return this;    }    public Object get(String name) {        return map.get(name);    }    public <R> R get(String name, Function<Object, R> mapper) {        Object value = get(name);        if (null == value) {            return null;        }        return mapper            .apply(value);    }    public <R> R get(String name, Class<R> type) {        Object value = get(name);        if (null == value) {            return null;        }        if (type.isAssignableFrom(value.getClass())) {            return type                .cast(value);        }        throw new ClassCastException(String            .format("%s -> %s", value.getClass(), type));    }}和類稱為Token:public class Token {    private String value;    public String getValue() {        return value;    }    public void setValue(String value) {        this.value = value;    }    public Token withValue(String value) {        setValue(value);        return this;    }}最后是班級的測試Token班public class TokenTest {    @Test    public void verifyToken() {        verify("bar", new Token()            .withValue("bar"));    }    @Test    public void verifyContainer() {        Container tokens = new Container()            .with("foo", "bar")            .with("baz", "bat");        verify("bar", tokens.get("foo", String.class));        verify("bat", tokens.get("baz", String::valueOf));  // line 21    }    private void verify(String expected, String actual) {        verify(expected, new Token()            .withValue(actual));    }    private void verify(String expected, Token actual) {        Assert            .assertEquals(expected, actual.getValue());    }}
查看完整描述

2 回答

?
繁星淼淼

TA貢獻1775條經驗 獲得超11個贊

根據JLS §15.12.2.2

參數表達式被認為與潛在適用方法的適用性相關,m除非它具有以下形式之一:

  • 一個隱式類型的 lambda 表達式1

  • 一個不精確的方法引用表達式2。

  • [...]

所以:

verify("bar", tokens.get("foo", e -> String.valueOf(e)));

在重載解析期間,隱式類型的 lambda 表達式e -> String.valueOf(e)從適用性檢查中跳過 - 兩種verify(...)方法都適用 - 因此存在歧義。

相比之下,這里有一些可行的示例,因為類型是明確指定的:

verify("bar", tokens.get("foo", (Function<Object, String>) e -> String.valueOf(e)));

verify("bar", tokens.get("foo", (Function<Object, String>) String::valueOf));

1 - 隱式類型的 lambda 表達式是一個 lambda 表達式,其中推斷出其所有形式參數的類型。
2 - 一個不精確的方法引用 - 一個有多個重載的方法。


查看完整回答
反對 回復 2022-12-15
?
qq_笑_17

TA貢獻1818條經驗 獲得超7個贊

String.valueOf(...)不同參數的多種實現。編譯器不知道你要調用哪一個。編譯器無法看到所有可能的方法實際上都返回 a String,因此調用哪個方法并不重要。由于編譯器不知道返回類型是什么,因此它無法推斷出Function<...,...>表達式的類型,因此它無法理解您手頭是否會有 aFunction或其他東西,因此無法判斷您是否想調用該get方法一個Function或一個Class


如果您不String::valueOf使用 usee -> String.valueOf(e)那么編譯器可以推斷出更多,但它仍然不會理解您將始終返回 aString并因此將其解釋為Function<Object, Object>您的verify方法有問題。


e -> e.toString我不完全理解,我不明白為什么編譯器不能在String這里推斷為返回類型。它推斷Object并執行與前一個案例完全相同的事情。如果您將操作拆分為

String s = tokens.get("baz", e -> e.toString());
verify("bat", s);  // line 21

那么它就可以工作了,因為編譯器可以Rs. 通過顯式指定,它的工作方式相同R

verify("bat", tokens.<String>get("baz", e -> e.toString()));  // line 21

String.class編譯器很容易理解您要調用該get(Class)方法。


Object::toString因為編譯器知道這將是一個Function<Object, String>.


查看完整回答
反對 回復 2022-12-15
  • 2 回答
  • 0 關注
  • 154 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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