当使用ClassName.method()时,首先使用Compiler,Static或instance方法查找哪个方法?

我想正确理解为什么在编译错误之下? 根据我的理解如果我使用Test.xyz()然后编译器只查找静态方法而不是实例方法然后为什么在编译失败?

class Test { public static void main(String arg[]) { Test.xyz(10); // compilation fail } public void xyz(int i) { } public static void xyz(Integer i) { } } 

每个人请建议为什么编译失败而不是其他建议和如何使用, 我知道所有基本的东西Autoboxing等。

为什么会出现编译错误

编译通过不同的步骤进行。 从JLS中提取,以下是解释您遇到此错误的原因的规则。

我跳过了与你的情况无关的第一步 。 一切都发生在同一个class级。

第二步: 确定方法签名

可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。 最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换 ,或使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

从上面的注释中,您使用Test.xyz(10);调用的方法Test.xyz(10); 是一个采用int参数的那个:

 public void xyz(int i) {} 

但现在,还有第三步: 选择合适的方法

如果方法调用在左括号之前具有TypeNameforms的MethodName 标识符 ,或者左括号之前的方法调用,具有TypeNameforms。 NonWildTypeArguments标识符,然后编译时声明必须是静态的 ,否则会发生编译时错误。

同样,从上面的注释中,您以staticforms调用该方法,

 Test.xyz(10); 

但不幸的是,从第二步中选择的方法并不是静态的。

这就是为什么像Eclipse这样的IDE会建议“将’xyz()’改为静态”。

但正如我在第一个答案(删除)中所解释的那样,您可以在类Test的实例上调用public void xyz(int i) {} ,或者使用Integer参数调用static方法: Test.xyz(Integer.valueOf(10));

两者都有效。

你这里没有返回类型:

 public static xyz(Integer i) { } 

如果没有任何回报,这应该是无效的:

 public static void xyz(Integer i) { } 

而且,您还需要将第一个方法设为静态:

 public static void xyz(int i) { } 

因此可以从静态main方法中调用它。 无法使用静态方法调用非静态方法。 更详细的解释: 在Java中调用静态方法中的非静态方法

这就是我做静态类的方法。

 public class test { public static void main(String arg[]) { xyz(10); } public static void xyz(int i) { } } 

好的,所以这里有Java中的autoboxing概念。

你写道:

 Test.xyz(10); // Here 10 is a primitive int and not a java.lang.Integer object. 

但是由于您通过类名直接调用xyz方法,显然意味着您要访问类Testpublic static xyz(Integer)方法。

但是在编译过程中发生的事情是,首先你的javac编译器检查要访问的方法签名,然后检查它的访问权限( publicprivateprotecteddefault )和非访问( finalstaticetc )修饰语。

这段代码也发生了同样的事情。

Java做的第一件事是,它检查了签名xyz(int)的方法是否存在,而不是xyz(Integer)因为你已经传入10而不是new Integer(10)作为参数。

它找到了两种方法,
1. xyz(int)
2. xyz(Integer)

如果xyz(int)不存在,它将应用自动装箱的概念(即,自动将10转换为new Integer(10) )并选择要执行的xyz(Integer) 。 但是由于xyz(int)存在,它不会将10自动装箱到new Integer(10)并选择xyz(int)而不是xyz(Integer)

现在,由于您的编译器选择了要执行的xyz(int) ,它会检查它的非访问修饰符。 现在因为方法xyz(int)是非静态的,所以你需要使用Test类的对象访问它,如下所示:

 new Test().xyz(10); 

而且,如果要访问static xyz(Integer)方法,您可能必须使用:

 Test.xyz(new Integer(10)); // You have to maunally autobox it. 

希望这可以帮助。