开发者

Understanding which constructor is chosen and why

Why following program every time prints I'm string and not I'm object. or I'm int.?

public class Demo {

    public Demo(String s){
        System.out.println("I'm string");
    }

    public Demo(int i){
        System.out.println("I'm int.");
    }

    public Demo(Object o){
        System.out.println("I'm object.");
    }

    public static void main(String[] args) {
        new Demo(n开发者_运维知识库ull);
    }
}

Also if I replace int with Integer. It gives error as The constructor Demo(String) is ambiguous. Why?


null can be converted to Object or String, but not int. Therefore the second constructor is out.

Between the conversion to Object or the conversion to String, the conversion to String is more specific, so that's what's picked.

The JLS section 15.12.2 describes method overload resolution, and I believe the same approach is used for constructor resolution. Section 15.12.2.5 describes choosing the most specific method (constructor in this case):

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time type error.

This about the constructor invocation with Object or String arguments - any invocation handled by new Demo(String) could also be passed on to new Demo(Object) without a compile-time type error, but the reverse is not true, therefore the new Demo(String) one is more specific... and thus chosen by the overload resolution rules.


To answer your second question (since Jon Skeet has already covered the first), when you have both a String constructor and an Integer constructor the compiler doesn't know what you mean by null in new Demo(null): it could be either a String or an Integer.

Because String can't be cast to Integer (and vice versa) the compiler gives up and reports the ambiguous error. This is in contrast to the String vs Object choice when you don't have the Integer constructor.


When you have constructors or methods like the above, the compiler generally tries to find the closest match possible and uses that.

The way to think of null in these circumstances is it acts as a subtype of all types (yes, it's not strictly speaking true but it provides a good platform for thinking about what happens). So using this rule it fits string more closely than object, hence this is the constructor that is executed.


The fact the String constructor is mentioned in by the compiler in your second error:

The constructor Demo(String) is ambiguous.

is not significant. This is because the Constructor which takes a String is the first declared constructor, so the compiler uses it in its error message. Change to have the Object constructor first and you get:

The constructor Demo(Object) is ambiguous.

What it's trying to say is there's ambiguity between the constructor which takes the Integer and the Object, so you have to be more specific, as null can be applied to each. Integer IS-NOT-A String, so the two types are not compatible. You need to be more specific so the compiler can bind the constructor call.

See @Jon Skeet answer for why the compiler raises an error in some instances and not in others.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜