How Java choose most specific method to call A.K.A avoid is ambiguous for the type Other Error

If you ever try to play with Java you may have experience this compile error at least one time. “is ambiguous for the type Other” when you do experiment with method overloading this compile time error may disturbed you.  also you may have fix this error without proper understanding what has happen. also this type of questions can come when you go for technical interviews. so lets discuss that.

Story in simple

How to choose most suitable method is complex explanation. i don’t think anyone expecting a technical white paper here. so lets convert that to understandable english.

this become a problem when its comes to overloading. over loading means same method name and different number of OR same number but different type parameters. I hope you know that overloading is compile time binding. so this is evaluated and process in compile time. (that is what is ambiguous for the type Other comes in compile time) in other words same concept call as early binding. most suitable method chosen in compile time. as mentioned earlier when compiler choosing most suitable method it consider number of parameters and type of parameter.

there are few rules to learn. so be patients and go through all examples.

lets consider an example use case 001.

what below code will print?

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null);
	}

	private static void printIt(Object object) {
		System.out.println("Object method called");
	}

	private static void printIt(Number number) {
		System.out.println("Number method called");
	}
}

it will call Number parameter method and out put would be

Number method called

what is the reason. we are passing value as null. basically null can be assign to to any reference type variable. ( if you don’t understand this concept refer this article) when you pass null there are two methods eligible to call. as we discussed java considered number of parameters and types of parameters. since both expect 1 parameter first rule is out here. so only effective rule is type of parameter. one is Object other one is Number. as we know Object is parent for any reference type. that makes Number is child to Object. means Number is more specific than Object. so it will choose Number parameter method to execute.

Here is the rule. if its need to choose one from many then most child (most deepest in hierarchy) class get precedence over parent class. (Number is child of Object and Number got precedence.)

Hope we are clear. let make small change to prove this further more. without change existing code add new method from Integer type. ( I have purposely added this method as first method to avoid someone to think “last method will pick by compiler or there is some pattern over method position to select”

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null);
	}

	private static void printIt(Integer integer) {
		System.out.println("Integer method called");
	}

	private static void printIt(Object object) {
		System.out.println("Object method called");
	}

	private static void printIt(Number number) {
		System.out.println("Number method called");
	}

}
Integer method called

Now that confirmed our theory. if you confused why it choose Integer over Object and Number bellow image will give answer for you.

integerClass

yes.. Integer is child of Number. that is why when Integer method is not there it chosen Number (parent) and when Integer presents in chosen Integer despite the Number. because law of “selecting most child type in the tree”

Now lets make other change. without changing exsisting code add new method “String”

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null);
	}

	private static void printIt(Integer integer) {
		System.out.println("Integer method called");
	}

	private static void printIt(Object object) {
		System.out.println("Object method called");
	}

	private static void printIt(Number number) {
		System.out.println("Number method called");
	}
	
	private static void printIt(String number) {
		System.out.println("Number method called");
	}

}

Compile and run.. Oh..!!! its not allowed to compile.. it gives you compile error. (Recap: Overloading is compile time binding – early binding)

problem is why java cannot compile this? Object will go out as it has more child types here. (Integer , Number, String). Remains are Integer , Number and String.. Number also goes out as its child exist (Integer) in the game. so remains are String and Integer. What to choose.. you cant take any because

A) those are not in same branch so no one is parent of other.

B) Both are specific and no one can take over other as both in same level. so it make ambiguous.

The method printIt(Integer) is ambiguous for the type ObjectNumber
at com.krishantha.sample.java.specificmethod.ObjectNumber.main(ObjectNumber.java:5)

Lets consider complete different example to discuss this more.

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null);
	}

	private static void printIt(Object object) {
		System.out.println("Object method called");
	}
	
	private static void printIt(String number) {
		System.out.println("Number method called");
	}
	
	private static void printIt(ArithmeticException arithmeticException){
		System.out.println("ArithmeticException method called");
	}
}

here is same.. Ambiguous issue comes. why? Object is goes out as its parent for both ArithmeticException and Number. from other two both specific. but neither one than other so its ambiguous. now try replace by  String with Exception. (Yesterday I have posted this to stackoverflow to see what is the requirement of this type article (choosing specific methods). while some people are struggling some one given the answer. so couldn’t gets others opinions 🙁 )

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null);
	}

	private static void printIt(Object object) {
		System.out.println("Object method called");
	}
	
	private static void printIt(Exception number) {
		System.out.println("Number method called");
	}
	
	private static void printIt(ArithmeticException arithmeticException){
		System.out.println("ArithmeticException method called");
	}
}

now its make simple. ArithmeticException is the most specific one to choose.

Hope you are in good understanding now. finally lets consider multiple parameter example for more understanding

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null, null);
	}

	private static void printIt(Object object, Throwable throwable) {
		System.out.println("Object - Throwable method called");
	}

	private static void printIt(Number number, Exception exception) {
		System.out.println(" Number - Exception method called");
	}

	private static void printIt(Integer integer, RuntimeException runtimeException) {
		System.out.println("Integer - RuntimeException method called");
	}
}

this will chose below method.

	private static void printIt(Integer integer, RuntimeException runtimeException) {
		System.out.println("Integer - RuntimeException method called");
	}

because Integer is most specific in first parameter hierarchy and RunTimeException is most specific in second hierarchy. but if you change program as follows it will again cause ambiguity issue. because String is not in same inheritance tree with Exception and there fore cannot choose most specific one.

package com.krishantha.sample.java.specificmethod;

public class ObjectNumber {
	public static void main(String[] args) {
		printIt(null, null);
	}

	private static void printIt(Object object, Throwable throwable) {
		System.out.println("Object - Throwable method called");
	}

	private static void printIt(Number number, Exception exception) {
		System.out.println(" Number - Exception method called");
	}

	private static void printIt(Integer integer, String string) {
		System.out.println("Integer - String method called");
	}
}

Hope you are clear now. you can comment your questions and idea in bellow..

 

Share this on your world...Share on Facebook
Facebook
Share on Google+
Google+
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin
Email this to someone
email
Print this page
Print

Leave a Reply