参数中的Java类型提升 - java

我偶然发现了以下片段:

public class ParamTest {
    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, long b) {
        System.out.println("In long " + (a + b));
    }

    public static void printSum(double a, long b) {
        System.out.println("In doubleLONG " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

这将导致编译错误:

错误:(15,9)java:对printSum的引用不明确,在ParamTest中的方法printSum(int,double)和在ParamTest中的方法printSum(long,long)都匹配

这是如何模棱两可的?因为第一个参数已经是一个int,在这种情况下不应该仅提升第二个参数吗?在这种情况下,不需要推广第一个参数,对吗?

如果我更新代码以添加另一个方法,则编译成功:

public static void printSum(int a, long b) {
    System.out.println(String.format("%s, %s ", a, b));
}

让我扩大一下以澄清。下面的代码导致歧义:

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, long b) {
        System.out.println("In long " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

然后,下面的代码也将导致歧义:

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(double a, long b) {
        System.out.println("In doubleLONG " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

但是,这不会导致歧义:

public class ParamTest {

    public static void printSum(int a, double b) {
        System.out.println("In intDBL " + (a + b));
    }

    public static void printSum(long a, double b) {
        System.out.println("In longDBL " + (a + b));
    }

    public static void main(String[] args) {
        printSum(1, 2);
    }
}

参考方案

我认为这与JLS关于15.12.2.5. Choosing the Most Specific Method的特定规则有关。它指出:

如果可以访问多个成员方法并将其应用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。 Java编程语言使用选择最特定方法的规则。

文本进一步解释了Java如何选择最具体的方法:

非正式的直觉是,如果第一种方法处理的任何调用都可以传递给另一个方法而没有编译时错误,则一个方法比另一种方法更具体。在诸如显式键入的lambda表达式参数(第15.27.1节)或可变Arity调用(第15.12.2.4节)的情况下,允许某种灵活性使一个签名适应另一个签名。

在您的示例中,所有方法都是可访问的,并且适用于方法调用,因此,Java需要确定其中最具体的方法。

对于这些方法,没有一个可以确定为更具体:

public static void printSum(int a, double b) {
    System.out.println("In intDBL " + (a + b));
} // int, double cannot be passed to long, long or double, long without error

public static void printSum(long a, long b) {
    System.out.println("In long " + (a + b));
} // long , long cannot be passed to int, double or double, long without error

public static void printSum(double a, long b) {
    System.out.println("In doubleLONG " + (a + b));
} // double, long cannot be passed to int, double or long, long without error

第四种方法正是因为它满足了最具体的必要条件而清除了歧义。

public static void printSum(int a, long b) {
    System.out.println(String.format("%s, %s ", a, b));
}

也就是说,可以将(int,long)传递给(int,double),(long,long)或(double,long)而不会出现编译错误。

Java-搜索字符串数组中的字符串 - java

在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…

Java Globbing模式以匹配目录和文件 - java

我正在使用递归函数遍历根目录下的文件。我只想提取*.txt文件,但不想排除目录。现在,我的代码如下所示:val stream = Files.newDirectoryStream(head, "*.txt") 但是这样做将不会匹配任何目录,并且返回的iterator()是False。我使用的是Mac,所以我不想包含的噪音文件是.DS_ST…

Java RegEx中的单词边界\ b - java

我在使用\b作为Java Regex中的单词定界符时遇到困难。对于text = "/* sql statement */ INSERT INTO someTable"; Pattern.compile("(?i)\binsert\b");找不到匹配项Pattern insPtrn = Pattern.compile(&…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…