在Main方法中,我调用了foo(1),然后打印“foo a”。所以我不明白为什么编译器没有给我一个错误,因为这两个方法具有相同的名称。
我还尝试将它们设置为私有和公共,并且仍然可以正常工作..
然后当我把“foo b”方法放在“foo a”之上时,它会输出“foo b”。那么编译器是否按顺序搜索方法?
这是所有代码,
public class Practice{
public static void main(String[] args) {
foo(1);
}
private static void foo(int n){
System.out.println("foo a");
}
public static void foo(int n){
System.out.println("foo b");
}
}
答案 0 :(得分:3)
<德尔>嗯。我无法编译。 德尔>
我认为这可能与How does Java distinguish these multiple methods with the same name/signature?类似。
您是否从某处复制粘贴方法,或者您是否输入了它?
也许这也是以前编译工作的延续。您是否尝试清理项目(/删除可执行文件),然后重新编译/运行?
注意:代码不是 NORMALLY 编译。你需要在eclipse上忽略错误才能让它编译。</ p>
嗯它确实有效!我现在认为它必须是一个日食怪癖,因为我仍然无法使用javac进行编译。当你使用eclipse强制编译时,它必须使第一个有效。第二个抛出编译器错误,随后被eclipse忽略。因此,您始终打印链中第一个方法的结果。
遵循Narendra Pathai的建议并在编译的.class文件上运行javap确实只显示了一个foo方法:) [是的,我添加了-private标志]。
(结果): 编译自“Practice.java”
public class Practice extends java.lang.Object{
public Practice();
public static void main(java.lang.String[]);
public static void foo(int);
}
(如果您交换公共 - 私人): 编译自“Practice.java”
public class Practice extends java.lang.Object{
public Practice();
public static void main(java.lang.String[]);
private static void foo(int);
}
答案 1 :(得分:3)
不可能有重复的方法。即使是日食也会出错。
回答为什么它仍然可以运行:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
at Main.main(Main.java:4)
答案 2 :(得分:2)
我无法运行此代码(我假设它们在同一个类中),它抛出错误“已定义的方法....”我认为这是正确的,因为这两个方法具有相同的名称和相同的参数,所以重载不适用于此处。我不认为改变公共和私人可以改变这种行为。您确定可以无误地运行此代码吗?
答案 3 :(得分:2)
来自docs:
您不能声明多个具有相同名称和方法的方法 相同数量和类型的参数,因为编译器无法分辨 他们分开了。
无论您声称什么,此代码都无法编译。再次检查!
来自JLS(§8.4.2)的加法(对于roliu):
方法m1的签名是a的签名的子签名 方法m2如果:
m2与m1具有相同的签名,或
m1的签名与签名的擦除(§4.6)相同 m2。
如果是m1,则两个方法签名m1和m2是覆盖等效的 是m2或m2的子签名是m1的子签名。
使用声明两个方法是编译时错误 类中的覆盖等效签名。
由于两种方法foo()
具有相同的签名,因此override-equivalent
这意味着,根据规范,我们应该得到一个编译错误。
<强>更新强>
JDK版本中有a bug:5.0和6u21已修复 - 但是如果OP有较旧版本的JDK可以解释这个问题。
答案 4 :(得分:1)
来自JLS - 两种方法具有相同的签名if they have the same name and argument types;参数类型确定如下:
两个方法是“覆盖等效”是一个编译错误;也就是说,如果方法的形式参数具有相同的擦除,则它们是覆盖等效的。
根据我正在阅读的JLS,可见性修饰符和/或static
不会影响方法签名。因此,此代码无法在我的框中编译(Java 1.7.0_45)。
用外行的话来说:把它想象成有人要你开门。
除此之外,你面前有两扇门。 完全相同的门。
它们都是完全相同的颜色,纹理,形状,并且具有相同的门把手。
它们中甚至有相同的凹痕,叮咬和划痕。
他们希望你打开哪个门?甚至没有什么可以告诉他们甚至开始猜测哪一个是有效的。
这就是类型擦除的问题 - 如果你的方法具有相同的type erasure,并且最终是覆盖等价的,那么Java也面临着两个问题。除了对它进行猜测之外,它只是放下并要求你澄清。
答案 5 :(得分:0)
我可以复制OPs问题
public class TestDuplicate {
private static void foo(int n) {
System.out.println("foo a");
}
public static void foo(int n) {
System.out.println("foo b");
}
public static void main(String[] args) {
foo(1);
}
}
out:foo a
更多信息
{java.runtime.name=Java(TM) SE Runtime Environment, sun.boot.library.path=C:\Program Files\Java\jre7\bin, java.vm.version=23.7-b01, user.country.format=NO, java.vm.vendor=Oracle Corporation, java.vendor.url=http://java.oracle.com/, path.separator=;, java.vm.name=Java HotSpot(TM) 64-Bit Server VM, file.encoding.pkg=sun.io, user.country=US, user.script=, sun.java.launcher=SUN_STANDARD, sun.os.patch.level=Service Pack 1, java.vm.specification.name=Java Virtual Machine Specification, user.dir=C:\Workspace\StackOverflow, java.runtime.version=1.7.0_17-b02, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.endorsed.dirs=C:\Program Files\Java\jre7\lib\endorsed, os.arch=amd64, java.io.tmpdir=C:\Users\Maki\AppData\Local\Temp\, line.separator=
, java.vm.specification.vendor=Oracle Corporation, user.variant=, os.name=Windows 7, sun.jnu.encoding=Cp1252, java.library.path=C:\Program Files\Java\jre7\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\AMD APP\bin\x86_64;C:\Program Files (x86)\AMD APP\bin\x86;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;C:\Program Files\MiKTeX 2.9\miktex\bin\x64\;C:\Program Files\Java\jdk1.7.0_17\bin;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;., java.specification.name=Java Platform API Specification, java.class.version=51.0, sun.management.compiler=HotSpot 64-Bit Tiered Compilers, os.version=6.1, user.home=C:\Users\Maki, user.timezone=, java.awt.printerjob=sun.awt.windows.WPrinterJob, file.encoding=UTF-8, java.specification.version=1.7, java.class.path=C:\Workspace\StackOverflow\bin, user.name=Maki, java.vm.specification.version=1.7, sun.java.command=TestDuplicate, java.home=C:\Program Files\Java\jre7, sun.arch.data.model=64, user.language=en, java.specification.vendor=Oracle Corporation, user.language.format=no, awt.toolkit=sun.awt.windows.WToolkit, java.vm.info=mixed mode, java.version=1.7.0_17, java.ext.dirs=C:\Program Files\Java\jre7\lib\ext;C:\Windows\Sun\Java\lib\ext, sun.boot.class.path=C:\Program Files\Java\jre7\lib\resources.jar;C:\Program Files\Java\jre7\lib\rt.jar;C:\Program Files\Java\jre7\lib\sunrsasign.jar;C:\Program Files\Java\jre7\lib\jsse.jar;C:\Program Files\Java\jre7\lib\jce.jar;C:\Program Files\Java\jre7\lib\charsets.jar;C:\Program Files\Java\jre7\lib\jfr.jar;C:\Program Files\Java\jre7\classes, java.vendor=Oracle Corporation, file.separator=\, java.vendor.url.bug=http://bugreport.sun.com/bugreport/, sun.io.unicode.encoding=UnicodeLittle, sun.cpu.endian=little, sun.desktop=windows, sun.cpu.isalist=amd64}
我发现它很奇怪,语言规范没有说明使用不同访问修饰符的重复方法。
我的IDE(eclipse)抱怨方法的红色下划线警告我有关重复的方法,但代码编译并运行得很好。
答案 6 :(得分:0)
我刚刚在这里浏览了Java 7规范:http://docs.oracle.com/javase/specs/并且(隐式)描述的代码违反了规范。
以下是相关摘录:
8.4方法声明
方法声明可以调用的可执行代码,传递固定数字 值作为参数。
MethodDeclaration: MethodHeader MethodBody
MethodHeader: MethodModifiers_opt TypeParameters_opt结果MethodDeclarator Throws_opt
MethodDeclarator: 标识符(FormalParameterList_opt)
...
可以在名称中使用MethodDeclarator中的标识符来引用该方法。
类的主体使用覆盖等效签名(第8.4.2节)将两个方法声明为成员是一个编译时错误。
8.4.1正式参数
方法或构造函数的形式参数(如果有)由逗号分隔的参数说明符列表指定。
8.4.4通用方法
如果方法声明了一个或多个类型变量(§4.4),则该方法是通用的。这些类型变量称为方法的类型参数。
8.4.2方法签名
如果两个方法具有相同的名称和参数,则它们具有相同的签名 如果满足以下所有条件,则两个方法或构造函数声明M和N具有相同的参数类型:
•它们具有相同数量的形式参数(可能为零)
•它们具有相同数量的类型参数(可能为零)
•设A1,...,An为M的类型参数,让B1,...,Bn为N的类型参数。将N的类型中每次出现的Bi重命名为Ai后,对应的类型变量是相同的,M和N的形式参数类型是相同的。
方法m1的签名是方法m2的签名的子签名,如果:
•m2与m1具有相同的签名,或
•m1的签名与m2签名的擦除(§4.6)相同。
如果m1是a,则两个方法签名m1和m2是覆盖等价的 m2或m2的子签名是m1的子签名。
在类中声明两个具有覆盖等效签名的方法是一个编译时错误。
它定义方法名称的方式对我来说有点模棱两可,但我认为很清楚,唯一对签名冲突很重要的是:
答案 7 :(得分:0)
它也不会编译Eclipse
的 。
从命令提示符运行javac
(1.7):
Practice.java:13: error: method foo(int) is already defined in class Practice
public static void foo(int n){
^
1 error
答案 8 :(得分:0)
在此,定义 SAME 方法http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2
的内容two methods have the same signature if they have the same name and argument types.
所以你会得到一个编译时错误,那就是说:检查你的代码和IDE
It is a compile-time error to declare two methods with override-equivalent signatures in a class.
或许您正在运行以前的编译类文件
答案 9 :(得分:-2)
这是因为公共/私人设置。私有方法不能在obj之外访问..但是,公共方法可以,这不是错误。