我想正确理解为什么在编译错误之下? 根据我的理解如果我使用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等。
答案 0 :(得分:3)
编译通过不同的步骤进行。从JLS中提取,以下是解释您出现此错误的原因的规则。
我跳过与您的案例无关的first step。一切都发生在同一个班级。
第二步:Determine method signature
可能存在多种此类方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法调度的方法
第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。
从上面的评论中,您使用Test.xyz(10);
调用的方法是采用int
参数的方法:
public void xyz(int i) {}
但现在,还有第三步:Choosing the appropriate method
如果方法调用在左括号之前具有 TypeName形式的MethodName。标识符,或者如果左括号之前的方法调用具有TypeName形式。 NonWildTypeArguments标识符,然后编译时声明必须是静态的,否则会发生编译时错误。
同样,从上面的评论中,您以static
形式
Test.xyz(10);
但不幸的是,从第二步中选择的方法是不静态。
这就是为什么像Eclipse这样的IDE会建议“将'xyz()'改为静态”。
但正如我的第一个回答(已删除)中所述,您可以在课程public void xyz(int i) {}
的实例上调用Test
,或使用static
调用Integer
方法参数:Test.xyz(Integer.valueOf(10));
。
两者都有效。
答案 1 :(得分:1)
这里没有返回类型:
public static xyz(Integer i) {
}
如果没有任何回报,这应该是无效的:
public static void xyz(Integer i) {
}
而且,您还需要将第一个方法设为静态:
public static void xyz(int i) {
}
因此可以从静态main方法中调用它。无法使用静态方法调用非静态方法。有关此问题的更详细说明:calling non-static method in static method in Java
答案 2 :(得分:0)
这就是我做静态类的方法。
public class test {
public static void main(String arg[]) {
xyz(10);
}
public static void xyz(int i) {
}
}
答案 3 :(得分:0)
好的,这就是Java中autoboxing
的概念。
你写道:
Test.xyz(10); // Here 10 is a primitive int and not a java.lang.Integer object.
但是,由于您直接通过类名调用xyz
方法,因此显然意味着您要访问类public static xyz(Integer)
的{{1}}方法。
但是在编译过程中会发生什么,首先你的Test
编译器检查要访问的方法签名,然后检查它的访问权限javac
,{{1} },public
,private
)和非访问(protected
,default
,final
)修饰符。
这段代码也发生了同样的事情。
Java做的第一件事是,它检查了签名static
的方法是否存在,而不是etc
因为你传递了xyz(int)
而不是{{1} }作为参数。
它找到了两种方法,
1. xyz(Integer)
2. 10
如果new Integer(10)
不存在,它会应用自动装箱的概念(即自动将xyz(int)
转换为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
希望这会有所帮助。