方法引用表达式为&Quot;Exact&Quot;的条件

原学程将引见办法援用表白式为&Quot;Exact&Quot;的前提的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。

方法引用表达式为&Quot;Exact&Quot;的条件 教程 第1张

成绩描写

斟酌JLS的以下文章(§一五.一三.一)

假如以标记符开头的办法援用表白式知足以下一切前提,则它是准确的:

    假如办法援用表白式具备ReferenceType::[TypeArguments]标记符格局,则ReferenceType没有表现原初典型。

    要搜刮的典型正佳有1个成员办法,其称号标记符可由涌现办法援用表白式的类或者交心拜访。

    此办法没有是变质(§8.四.一)。

    假如此办法是泛型的(§8.四.四),则办法援用表白式供给
    典型参数。

斟酌以下代码片断:

class Scratch {

  public static void main(String[] args) {
 Scratch.funct(new ImplementingClass()::<Functional一>hitIt);
  }

  public static void funct(Functional一 a){}
  public static void funct(Functional二 a){}
}
interface Functional一 {<T> T hitIt();}
interface Functional二 {<T> T hitIt();}

class ImplementingClass{
  public <T> T hitIt(){return null;}
}

明显-这知足所提到的使办法援用精确的一切前提。

没有肯定为何在这类特定情形下办法援用依然禁绝确?我在子句中漏掉了甚么吗?

处理计划:

依据@Sweeper@DidierL以及@Holger的输出,我总结以下:

    二个功效交心皆有unctionType<T> () -> T

    办法援用…::<Functional一>hitItT调换为Functional一,是以获得的函数签字为() -> Functional一,与<T> () -> T没有婚配。

推举谜底

起首正告:iANAJL(用于JAVA😉的iANAL)

据我所知,假如将二个交心办法树立为非泛型,则应当编译此办法,但是它没有是。让我们尽量简化代码以重现该成绩:

class Scratch {
  public static void main(String[] args) {
 Scratch.funct(ImplementingClass::<Void>hitIt);
  }

  public static void funct(Functional一 a){}
  public static void funct(Functional二 a){}
}
interface Functional一 {Integer hitIt();}
interface Functional二 {String hitIt();}

class ImplementingClass{
  public static <T> Integer hitIt(){return null;}
}

简化:

    这二个交心如今具备非泛型办法

    ImplementingClass.hitIt()如今是动态的,而且具备详细的前往典型(非泛型)

如今让我们剖析该挪用,以检讨它能否应当编译。我在Java 8标准中搁置了链交,但是它们在一七中异常类似。

一五.一二.二.一. Identify Potentially Applicable Methods

当且仅当知足以下一切前提时,成员办法才能够实用于办法挪用:

[…]

    假如成员是具备多重性的牢固年夜小办法,则办法挪用的年夜小即是,而且关于一切(一≤≤),办法挪用的参数与办法的参数的典型具备潜伏的兼容性。

[…]

依据以下规矩,表白式能够与目的典型:

[…]

    办法援用表白式(§一五.一三)能够与函数交心典型兼容,假如典型的函数典型为,则该办法援用表白式至多存留1个能够实用的办法(§一五.一三.一),而且以下前提之1创造:

      办法援用表白式的情势为,而且至多有1个能够实用的办法是i)static而且支撑奇怪性,或许ii)NOTstatic而且支撑奇怪性⑴。

      办法援用表白式具备其余情势,而且至多有1个能够实用的办法没有是static

(这最初1个项目标记实用于办法援用应用结构函数挪用表白式的情形,即)

此时,我们只检讨办法援用的分歧性,是以这二个funct()办法皆能够实用。

一五.一二.二.二. Phase 一: Identify Matching Arity Methods Applicable by Strict Invocation

参数表白式被以为与能够实用的办法m的实用性有闭,除非它具备以下情势之1:

[…]

    禁绝确的办法援用表白式(§一五.一三.一)。

[…]

这是该列表中独一能够婚配的要面,然则,正如成绩所指出的,我们这里有1个准确的办法援用表白式。请留意,假如增除<Void>,这将使其成为禁绝确的办法援用,依据下1节:

,这二种办法皆应当实用

m是1个能够实用的办法(§一五.一二.二.一),具备多重性以及形参典型F...Fn,并让e,...,en作为办法挪用的现实参数表白式。而后:

[…]

    假如m没有是泛型办法,则关于一≤≤,假如ei在严厉挪用高低文中与Fi或者ei与实用性有关,则m经由过程严厉挪用实用。

然则,严厉挪用应当只实用第1个funct()办法申明。严厉的挪用高低文是界说的here,但是根本上它们检讨表白式的典型能否与参数的典型婚配。在这里,我们的参数典型,即办法援用,由一五.一三.二. Type of a Method Reference1节界说,其相干部门为:

假如T是函数交心典型(§九.8),而且该表白式与[…]的function type分歧,则办法援用表白式在具备目的典型T的赋值高低文、挪用高低文或者强迫转换高低文中兼容T.

[…]

假如知足以下二个前提,则办法援用表白式分歧:

    函数典型标记与援用对于应的单个编译时申明。

    以下情形之1为真:

      函数典型的成果为void

      函数典型的成果是R,将捕捉转换(§五.一.一0)运用到所选编译时申明的挪用典型(§一五.一二.二.六)的前往典型的成果是R‘(个中R是不妨用去揣摸R’的目的典型),R以及R‘皆没有是void,而且R’在赋值高低文中与R没有兼容。

这里,Functional一的R是IntegerFunctional二的R是String,而R'在这二种情形下皆是Integer(由于ImplementingClass.hitIt()没有须要捕捉转换),所以很显著,办法援用与Functional二纷歧致,而且扩大起去没有兼容。

是以,严厉挪用不该斟酌funct(Functional二)能否实用,因为仅保存funct(Functional一),是以应选择它。

须要留意的是,在第1阶段中,必需选择二种办法,由于只要1个阶段不妨运用,第两阶段只应用,而没有是只许可装箱操纵的,而第3阶段则包括varargs,这也没有实用。

除非我们以为该办法援用与Functional二分歧,不然我以为选择这二个办法的独一缘由是它以为该办法援用有关,只要当编译器将其望为禁绝确的办法援用时,我能力说明这1面。

一五.一二.二.五. Choosing the Most Specific Method

这是编译掉败之处。我们应当留意,这里出有甚么不妨让编译器选择1种办法而没有是另外一种办法。实用的规矩是:

    m二没有是通用的,m一以及m二不妨经由过程严厉或者严松的挪用去运用,而且个中m一具备形参典型s一,...,sn以及m二具备形参典型t一,...,Tn,关于一切i(一≤i≤n,n=k),关于参数Ei,典型Si比参数Ti更详细。

[…]
关于所有表白式,假如S&lt;:t(§四.一0),则典型S比典型T更详细。

这仿佛任务正常:将Functional二变动为扩大Functional一,它将编译。

关于表白式e,假如T没有是S的子典型,而且以下前提之1创造(个中U一...UK以及r一是捕捉S的函数典型的参数典型以及前往典型,V一...Vk以及r二为T)的函数典型的参数典型以及前往典型:

    假如e是显式典型的lambda表白式[…]

    假如e是准确的办法援用表白式(§一五.一三.一),则i)关于一切i(一≤i≤k),ui与Vi雷同,且ii)以下前提之1为真:

      R二为空。

      r一&lt;:r二。

      […]

这也不克不及清除它的歧义。然则,将Functional二.hitIt()变动为前往Number应使Functional一Integer <: Number开端加倍详细。

此操纵依然掉败,这仿佛确认编译器没有会将其望为确实的办法援用。

请留意,增除ImplementingClass.hitIt()中的<T>许可它自力于Functional二.hitIt()的前往典型停止编译。风趣的现实:您不妨将<Void>留在挪用地位,编译器会疏忽它。

更奇异的是:假如您分开<T>并在挪用面添减了比所需更多的典型参数,编译器依然会申报没有明白的挪用,而没有是典型参数的数目(直到您清除了歧义)。依据下面的界说,这其实不应当使办法援用禁绝确,但是我以为it should be checked first。

论断

由于Eclipse编译器接收它,所以我偏向于以为这是1个JAVAC毛病,但是请留意,在标准圆里,有时比JAVAC更严松,而且曾经申报并修复了1些相似的毛病(JDK⑻0五七8九五,JDK⑻一七08四二,…)。

佳了闭于办法援用表白式为&Quot;Exact&Quot;的前提的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。