为什么输出是这样的?

发布于 2024-09-05 18:19:56 字数 537 浏览 2 评论 0原文

class Another {
    public void method(Object o) {
        System.out.println("This is in method which takes object");
    }
    public void method(String s) {
        System.out.println("This is method which takes string");
    }
}

public class NewClass {
    public static void main(String args[]) {
        Another an = new Another();
        an.method(null);
    }
}

当我尝试执行此操作时,我得到

这是采用字符串的方法

这是将字符串作为输出的 。为什么不“这是在接受对象的方法中”?对象也可以为空,字符串也可以为空,为什么它不调用第一个方法?

class Another {
    public void method(Object o) {
        System.out.println("This is in method which takes object");
    }
    public void method(String s) {
        System.out.println("This is method which takes string");
    }
}

public class NewClass {
    public static void main(String args[]) {
        Another an = new Another();
        an.method(null);
    }
}

When I try to execute this, I get

This is method which takes string

as the output. Why not "This is in method which takes object"? Object can also be null and string can also be null, why doesn't it invoke first method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

撞了怀 2024-09-12 18:19:56

根据 Java 语言规范,在重载方法的情况下,两个方法都可以处理提供的参数,则选择具有更具体参数的方法。由于 StringObject 更具体(String extends Object),void method(String)< /code> 被选择并调用。

According to the Java Language Specification, in such cases of overloaded methods where both methods can handle the provided arguments, the method with more specific argument is chosen. Since String is more specific than Object (String extends Object), void method(String) is chosen and called.

旧城烟雨 2024-09-12 18:19:56

这与 JLS 中的指定完全相同:

JLS 15.12.2.5 选择最具体的方法

如果多个成员方法既可访问又适用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。 Java 编程语言使用选择最具体方法的规则。

String 是一个Object,但并非所有Object 都是String。因此,StringObject更具体,这也是为什么在上面的示例中选择 String 重载的原因。


值得注意的是,这个确切的问题(本质上)出现在精彩的 Java Puzzlers 中(强烈推荐),特别是谜题 46:令人困惑的构造函数的案例

Java 的重载解析过程分两个阶段进行。第一阶段选择所有可访问且适用的方法或构造函数。第二阶段选择第一阶段中选择的最具体方法或构造函数。如果一个方法或构造函数可以接受传递给另一个方法或构造函数的任何参数,则该方法或构造函数的具体性不如另一个方法或构造函数

理解这个难题的关键是测试哪种方法或构造函数最具体并不使用实际参数:调用中出现的参数。它们仅用于确定哪些重载适用。一旦编译器确定哪些重载适用且可访问,它就会选择最具体的重载,仅使用形式参数:出现在声明中的参数。


我将引用Effective Java 2nd Edition第 41 条:明智地使用重载来结束:

决定选择哪种重载的规则极其复杂。它们在语言规范中占据了三十三页,很少有程序员能够理解它们的所有微妙之处。

不用说,这本书也强烈推荐

另请参阅


关于显式转换

那么如何使用 null 参数调用 Object 重载呢?

简单:将 null 转换为 Object 类型。在多种情况下这是有用/必要的,这就是其中之一。

如果我有一个重载,例如需要一个Integer怎么办?

那么方法调用不明确,并且发生编译时错误。

JLS 15.12.2.5 选择最具体的方法

可能没有一种方法是最具体的,因为有两种或多种方法是最具体的。在这种情况下[...有一些例外]我们说方法调用不明确,并且发生编译时错误。

要解决歧义,您可以再次将 null (或其他表达式)转换为所需的重载类型。

另请参见

This is exactly as specified in JLS:

JLS 15.12.2.5 Choosing the Most Specific Method

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

A String is-a Object, but not all Object is-a String. Therefore, String is more specific than Object, hence why the String overload is chosen in the above example.


It is worth noting that this exact question (in essence) appeared in the wonderful Java Puzzlers (highly recommended), specifically Puzzle 46: The Case of the Confusing Constructor

Java's overload resolution process operates in two phases. The first phase selects all the methods or constructors that are accessible and applicable. The second phase selects the most specific of the methods or constructors selected in the first phase. One method or constructor is less specific than another if it can accept any parameters passed to the other

The key to understanding this puzzle is that the test for which method or constructor is most specific does not use the actual parameters: the parameters appearing in the invocation. They are used only to determine which overloadings are applicable. Once the compiler determines which overloadings are applicable and accessible, it selects the most specific overloading, using only the formal parameters: the parameters appearing in the declaration.


I will close with a quote from Effective Java 2nd Edition, Item 41: Use overloading judiciously:

The rules that determine which overloading is selected are extremely complex. They take up thirty-three pages in the language specification, and few programmers understand all of their subtleties.

Needless to say, this book is also highly recommended.

See also


On explicit casting

So how can I invoke the Object overload with null argument?

Simple: cast the null to type Object. There are several scenarios where this is useful/necessary, and this is one of them.

What if I have an overload that takes, say, an Integer?

Then the method invocation is ambiguous, and compile-time error occurs.

JLS 15.12.2.5 Choosing the Most Specific Method

It is possible that no method is the most specific, because there are two or more methods that are maximally specific. In this case [... with some exceptions] we say that the method invocation is ambiguous, and a compile-time error occurs.

To resolve the ambiguity, again you can cast the null (or other expression) to the desired overload type.

See also

郁金香雨 2024-09-12 18:19:56

在解析重载方法调用时,编译器将始终找到可能的最窄匹配。

顺便说一句,Java 约定是对类使用大写名称,即 Another

The compiler will always find the narrowest match possible when resolving overloaded method calls.

Btw the Java convention is to use uppercase names for classes, i.e. Another.

紙鸢 2024-09-12 18:19:56

我相当确定,在这种情况下,使用 Java 6(我认为 Java 5 会引发编译器错误),它将选择最低级别的类来将 null 归因于。 (由于 String 是一个对象,因此它在层次结构中处于较低位置)

I'm fairly certain that with Java 6 (I think Java 5 would have thrown a compiler error) in a case like this, it will select tho lowest level class to attribute the null to. (since String is an Object it is lower in the hierarchy)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文