簡體   English   中英

Java:編譯時解析和“最具體的方法”,因為它適用於變量arity

[英]Java: compile-time resolution and “most specific method” as it applies to variable arity

有人可以幫助我理解JLS的第15.12.2.5節:最具體的方法嗎?

(來自JLS的強行剪切和粘貼如下)

另外,一個名為m的變量arity成員方法比另一個具有相同名稱的變量arity成員方法更具體:

  • 一個成員方法有n個參數,另一個成員方法有k個參數,其中n> = k。 第一個成員方法的參數類型是T1 ,. ,Tn-1,Tn [],其他方法的參數類型是U1 ,. ,Uk-1,英國[]。 如果第二種方法是通用的,那么讓R1 ... Rp p1成為它的形式類型參數,讓Bl成為Rl的聲明邊界,1lp,讓A1 ... Ap成為推斷的實際類型參數(§15.12.2.7)對於這種在初始約束條件下的調用Ti << Ui,1ik-1,Ti << Uk,kin和let Si = Ui [R1 = A1,...,Rp = Ap] 1ik; 否則讓Si = Ui,1ik。 然后:對於從1到k-1的所有j,Tj <:Sj,並且對於從k到n的所有j,Tj <:Sk,並且,如果第二種方法是如上所述的通用方法,那么Al <:Bl [R1 = A1,...,Rp = Ap],1lp。
  • 一個成員方法具有k個參數,另一個具有n個參數,其中n> = k。 第一種方法的參數類型是U1 ,. ,Uk-1,Uk [],其他方法的參數類型是T1 ,. 。,Tn-1,Tn []。 如果第二種方法是通用的,那么讓R1 ... Rp p1成為它的形式類型參數,讓Bl成為Rl的聲明邊界,1lp,讓A1 ... Ap成為推斷的實際類型參數(§15.12.2.7)對於這種在初始約束條件下的調用,Ui << Ti,1ik-1,Uk << Ti,kin和令Si = Ti [R1 = A1,...,Rp = Ap] 1in; 否則讓Si = Ti,1in。 然后:對於從1到k-1的所有j,Uj <:Sj,並且對於從k到n的所有j,Uk <:Sj,並且,如果第二種方法是如上所述的通用方法,則Al <:Bl [R1 = A1,...,Rp = Ap],1lp。

忽略問題泛型,這是否意味着varargs比子類型更重要,或者在確定一種方法是否比另一種更具體時,子類型比varargs更重要? 我無法弄清楚。

具體示例:根據JLS,以下哪個compute()方法“更具體”?

package com.example.test.reflect;

class JLS15Test
{
    int compute(Object o1, Object o2, Object... others) { return 1; }
    int compute(String s1, Object... others)            { return 2; }

    public static void main(String[] args) 
    {
        JLS15Test y = new JLS15Test();
        System.out.println(y.compute(y,y,y));
        System.out.println(y.compute("hi",y,y));
    }
}

我無法弄清楚哪個是“更具體”; 輸出打印

1
2

我很困惑如何解釋結果。 當第一個參數是String時,編譯器選擇具有更具體子類型的方法。 當第一個參數是Object時,編譯器選擇具有較少可選varargs的方法。


注意 :如果您沒有閱讀JLS的這一部分,並且您給出的答案取決於參數的類型,那么您並沒有幫助我。 如果你仔細閱讀JLS,除了與泛型相關的部分,“更具體”的定義取決於聲明的參數,而不是實際的參數 - 這在JLS的其他部分發揮作用(找不到)它此刻)。

例如,對於固定的arity方法, compute(String s)將比compute(Object o)更具體。 但我試圖理解JLS的相關部分:變量arity方法。

  1. 當你調用compute("hi",y,y)int compute(String s1, Object... others)更具體,因為String是Object的子類。

  2. int compute(Object o1, Object o2, Object... others)compute(y,y,y)唯一匹配,因為第二個方法接收String作為第一個參數,而JLS15Test不是String的子類

編輯

我的答案取決於具體方法的基礎知識,但您的代碼只能編譯,因為編譯器能夠以上述方式區分方法。

以下示例甚至不會編譯,因為它的含糊不清:

情況1:

int compute(Object o1, Object o2, Object... others) { return 1; }
int compute(Object s1, Object... others)            { return 2; }

public static void main(String[] args) 
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute(y,y,y));
    System.out.println(y.compute("hi",y,y));
}

案例2:

int compute(String o1, Object o2, Object... others) { return 1; }
int compute(Object s1, String... others)            { return 2; }

public static void main(String[] args) 
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute("hi","hi","hi"));
}

更多編輯

前兩次我沒有得到你的問題(我希望我這次做:))。

您正在談論的實際案例將如下所示:

public class Test {
    public static void main(String[] args)
    {
        Test t = new Test();
        int a = t.compute("t", new Test());
        System.out.println(a);
    }

    int compute(String s, Object... others) { return 1; }
    int compute(Object s1, Object others)   { return 2; }
}

在這種情況下, compute(Object s1, Object others)確實比compute(String s, Object... others)更具體(參數更少),因此輸出確實是2

多次閱讀JLS后,我終於想到了解這一節。

他們所說的是,如果有兩個變量arity方法,為了決定哪個是“更具體”,你可以考慮擴展一個具有較短參數列表的方法,使其長度與長一個相等。 。 例如

int compute(Object o1, Object o2, Object... others)
int compute(String s1, Object... others)

可以考慮(僅用於“更具體”的目的)等同於

int compute(Object o1, Object o2, Object... others)
int compute(String s1, Object,    Object... others)

然后逐個比較參數類型,后一種方法更具體。

(更嚴格的是,第一個具有n = 3,k = 2,n> = k,具有String <:Object [String是Object的子類型]並且JLS規定直接比較每個參數的類型為j在1和之間k-1 [比較短的長度小1],將較短方法簽名的vararg類型與較長方法的其余參數進行比較。)

在以下情況中:

int compute(Object o1, Object o2, String... strings)
int compute(Object o1, String... strings)

這些將是等效的(僅用於“更具體”的目的)

int compute(Object o1, Object o2, String... strings)
int compute(Object o1, String,    String... strings)

而后者更具體。

所以變量arity從不勝過子類型,以便比較“更具體”的方法,這兩種方法都是變量arity。

但是,在變量方法之前,始終首先考慮固定方法(JLS 15.12.2.2和15.12.2.3)。

第二個計算調用打印2,因為文字“hi”在編譯時已知為String,因此編譯器會選擇第二個方法簽名,因為String比Object更具體。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM