当前位置: 首页 > 面试题库 >

Java:适用于可变Arity的编译时解析和“最特定的方法”

朱浩大
2023-03-14
问题内容

有人可以帮助我了解JLS第15.12.2.5节“
re:最具体的方法”
吗?

(来自JLS的糟糕的剪切和粘贴如下)

此外,如果满足以下任一条件,则一个名为m的可变arity成员方法比具有相同名称的另一可变arity成员方法更具体:

  • 一个成员方法具有n个参数,另一个具有k个参数,其中n> = k。第一种成员方法的参数类型为T1,…。。。,Tn-1,Tn
    [],另一种方法的参数类型为U1,。。。,Uk-1,Uk []。如果第二种方法是通用的,则将R1 … Rp
    p1作为其形式类型参数,将Bl作为R1的声明界限,1lp,让A1 … Ap是推断出的实际类型参数(第15.12.2.7节)对于在初始约束Ti <<
    Ui,1ik-1,Ti << Uk,kin下的调用,令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,…,Uk。。。,Tn-1,Tn []。如果第二种方法是通用的,则将R1 … Rp
    p1作为其形式类型参数,将Bl作为R1的声明界限,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比子类型更重要,或者subtyping比varargs更重要?我不知道。

具体示例:compute()根据JLS ,以下哪种方法“更具体”?

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
re:变量Arity方法的相关部分。


问题答案:

多次阅读JLS之后,我终于认为我理解了本节。

他们的意思是,如果有两种可变参数方法,为了确定哪种方法更“具体”,可以考虑将参数列表较短的方法扩展为与较长方法相同的长度。 。例如

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
[比较短的长度小一个],将较短方法签名的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方法(JLS 15.12.2.2和15.12.2.3),而不是可变arity方法。



 类似资料:
  • 问题内容: 在Java语言规范的15.12.2.5节中,它讨论了如何在具有固定arity的方法和可变arity的方法(即 )的情况下选择最具体的方法。 我在JLS中找不到关于在两种方法之间 做出 决定的方法,其中 一种是固定变量,另一种是可变变量 。例如: 可以按预期 进行 编译( 出于下面Yoni概述的原因 )。此调用代码还可以编译: 如果您运行它,(即non- varargs方法)将被调用。为

  • 问题内容: 哪种Java的CLI解析器比其他CLI解析器更易于使用和扩展? 问题答案: 这里是一些最受欢迎的。它们都是非常漂亮的功能,并且使用了前两个,我可以推荐它们。 Commons CLI http://commons.apache.org/cli/ Java宝石 http://code.google.com/p/javagems/ picocli (具有彩色使用帮助和自动完成功能) http

  • 问题内容: 我需要阅读较小的XML文件(最多只有几MB,UTF-8编码),四处寻找各种元素和属性,也许要修改一些并将XML重新写回磁盘(最好采用缩进格式) 。 什么是满足我需求的最佳XML解析器?有很多可供选择。我知道的一些是: JDOM Woodstox XOM dom4j VTD-XML Xerces-J Crimson 当然是JDK中的那个(我正在使用Java 6)。我对Xerces很熟悉,

  • 问题内容: 我以前使用过XML Parser,尽管它工作正常,但总体上我并不满意,感觉好像我在使用变通办法来处理应该是基本功能的事情。 我最近看到了SimpleXML,但还没有尝试过。有没有更简单的方法?两者都有哪些优点和缺点?您使用过其他解析器吗? 问题答案: 我不得不说,SimpleXML是蛋糕,因为它首先是用C编写的扩展,并且非常快。但第二,解析后的文档采用PHP对象的形式。这样您就可以像“

  • 问题内容: 我正在使用Java开发应用程序,该应用程序需要做一些复杂的逻辑规则推演,并将其作为功能的一部分。我想用Prolog或其他逻辑/约束编程语言(而不是Java)编写我的逻辑推论,因为我相信生成的代码将大大简化和维护。 我在Prolog上搜索了嵌入式Java实现,并找到了很多,每个文档都很少。我的(适度)选择标准是: 应该可嵌入Java中(例如,可以与我的Java软件包捆绑在一起,而不需要在

  • 我的输入: 我的输出需要为: 我错误的(解析)输出: 这是我的正则表达式: 演示:https://regex101.com/r/qltpwb/7