JAVA:具有相同名称的方法?

时间:2013-11-16 04:23:57

标签: java methods overloading

在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");
  }

}

10 个答案:

答案 0 :(得分:3)

<德尔>嗯。我无法编译。

我认为这可能与How does Java distinguish these multiple methods with the same name/signature?类似。

您是否从某处复制粘贴方法,或者您是否输入了它?

也许这也是以前编译工作的延续。您是否尝试清理项目(/删除可执行文件),然后重新编译/运行?

注意:代码不是 NORMALLY 编译。你需要在eclipse上忽略错误才能让它编译。<​​/ p>

嗯它确实有效!我现在认为它必须是一个日食怪癖,因为我仍然无法使用javac进行编译。当你使用eclipse强制编译时,它必须使第一个有效。第二个抛出编译器错误,随后被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)

编译时错误 - 重复方法

不可能有重复的方法。即使是日食也会出错。

enter image description here

回答为什么它仍然可以运行:

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的子签名。

     

在类中声明两个具有覆盖等效签名的方法是一个编译时错误。

它定义方法名称的方式对我来说有点模棱两可,但我认为很清楚,唯一对签名冲突很重要的是:

  1. 方法名称
  2. 泛型类型参数(如果有)
  3. 输入参数

答案 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之外访问..但是,公共方法可以,这不是错误。