当前位置: 首页 > 知识库问答 >
问题:

Java重载规则

谷梁嘉悦
2023-03-14
private void f(int a) { /* ... */ }
private void f(int a, int... b) { /* ... */ }

f(12); // calls the former? I would expect it to
f(12, (int[])null); // calls latter, but passes null for b? 
  // Can I force the compiler to call the second method in the same fashion
  // as would happen if the first method didn't exist?
interface A {}
class B implements A {}
class C implements A {}

private void f(A a) {}
private void f(B b) {}

f(new C()); // calls the first method
f(new B()); // calls the second method?
f((A)(new B()); // calls the first method using a B object?

这是两个示例,但是作为代码阅读器,我更喜欢一个用于解决此问题的精确有序规则的规范列表,因为我经常没有时间设置构建环境来检查编译器正在做什么。

共有1个答案

朱渝
2023-03-14

重载与重写

方法的正确实现的选择是在运行时完成的,正如您所指出的,现在要调用的方法的签名是在编译时决定的。

在编译时重载方法选择

通常,如果varargs方法与其他候选方法竞争,它们是最后选择的方法,因为它们被认为比接收相同参数类型的方法更不特定。

要验证它的编译时性质,可以进行以下测试。

声明一个类似的类并编译它(即javac chooseMethod.java)。

public class ChooseMethod {
   public void doSomething(Number n){
    System.out.println("Number");
   }
}

声明第二个类,调用第一个类的方法并编译它(即javac methodchooser.java)。

public class MethodChooser {
   public static void main(String[] args) {
    ChooseMethod m = new ChooseMethod();
    m.doSomething(10);
   }
}

如果运行该程序(即Java MethodChooser),则输出为Number

现在,向ChooseMethod类添加第二个更具体的重载方法,并重新编译它(但不要重新编译另一个类)。

public void doSomething(Integer i) {
 System.out.println("Integer");
}

如果再次运行main,输出仍然是number

基本上,因为它是在编译时决定的。如果重新编译MethodChooser类(带有main的类),并再次运行该程序,输出将是Integer

因此,如果要强制选择重载方法之一,则参数的类型必须与编译时的参数类型相对应,而不仅仅是在运行时。

在运行时重写方法选择

public class ChooseMethodA {
   public void doSomething(Number n){
    System.out.println("Number A");
   }
}

然后声明第二个扩展类并编译:

public class ChooseMethodB extends ChooseMethodA {  }

在MethodChooser类中,您可以执行以下操作:

public class MethodChooser {
    public static void main(String[] args) {
        ChooseMethodA m = new ChooseMethodB();
        m.doSomething(10);
    }
}

如果运行它,将得到输出编号A,这是可以的,因为该方法在ChooseMethodb中没有被重写,因此调用的实现是ChooseMethoda的实现。

现在,在methodchooserb中添加一个重写的方法:

public void doSomething(Number n){
    System.out.println("Number B");
}

重新编译这个方法,然后再次运行main方法。

现在,您将得到输出编号b

 类似资料:
  • 问题内容: 我之所以学习,是因为我参加了考试,而大多数Java并没有很多问题,但是我偶然发现了一个我无法解释的规则。这是一个代码片段: 返回: 1 3 1 3 虽然我希望它会返回: 1 3 1 4 为什么a2的类型确定在AX中调用哪种方法? 我一直在阅读有关重载规则和继承的文章,但这似乎晦涩难懂,以至于我无法找到确切的规则。任何帮助将不胜感激。 问题答案: 这些方法调用的行为由Java语言规范(参

  • 当我运行这段代码时,它会打印。我的问题是为什么没有编译时错误?对象和字符串的默认值为NULL。那么为什么不编译器说。

  • 运算符重载是通过函数重载实现的,概念上大家都很容易理解,这节我们来说一下运算符重载的注意事项。 1) 并不是所有的运算符都可以重载。能够重载的运算符包括: +  -  *  /  %  ^  &  |  ~  !  =  <  >  +=  -=  *=  /=  %=  ^=  &=  |=  <<  >>  <<=  >>=  ==  !=  <=  >=  &&  ||  ++  --  ,

  • Java 允许同一个类中定义多个同名方法,只要它们的形参列表不同即可。 如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,这种情况被称为方法重载(overload)。 例如,在 JDK 的 java.io.PrintStream 中定义了十多个同名的 println() 方法。 这些方法完成的功能类似,都是格式化输出。根据参数的不同来区分它们,以进行不同的格式化处理和输出。它们之

  • dml2select Description:将数据库更新请求转换为只读查询请求,便于执行EXPLAIN Original: DELETE FROM film WHERE length > 100 Suggest: select * from film where length > 100 star2columns Description:为SELECT *补全表的列信息 Original:

  • 问题内容: 假设我在课堂上说两种方法 和 那是什么感觉 重载还是重载? 问题答案: 重载是指两个或多个具有相同名称但参数不同的方法,就像您的示例一样。重载是从接口或抽象类实现一个方法的,因此超类中的方法具有实现,而子类中的方法具有不同的实现,它们仍然具有相同的方法名称和参数。