How do overloaded methods work? - java

public class Test1 {
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.testMethod(null);
}
public void testMethod(String s){
System.out.println("Inside String Method");
}
public void testMethod(Object o){
System.out.println("Inside Object Method");
}
}
When I try to run the given code, I get the following output:
Inside String Method
Can anyone explain why the method with the String type parameter is getting called?

most specific method argument is chosen for overloaded methods
In this case, String is subclass of Object. Hence String becomes more specific than Object. Hence Inside String method is printed.
Directly from JLS-15.12.2.5
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.
As BMT and LastFreeNickName have correctly suggested, (Object)null will cause overloaded method with Object type method to be called.

Adding on to an existing reply, I'm not sure if this is because of a newer Java version since the question, but when I tried to compile the code with a method taking an Integer as a parameter instead of an Object, the code still did compile. However, the call with null as the parameter still invoked the String parameter method at run-time.
For example,
public void testMethod(int i){
System.out.println("Inside int Method");
}
public void testMethod(String s){
System.out.println("Inside String Method");
}
will still give the output:
Inside String Method
when called as:
test1.testMethod(null);
The main reason for this is because String does accept null as a value and int doesn't. So null is classified as a String Object.
Coming back to the question asked, The type Object is encounter only when a new object is created. This is done by either type casting null as an Object by
test1.testMethod((Object) null);
or using any type of object for a primitive data type such as
test1.testMethod((Integer) null);
or
test1.testMethod((Boolean) null);
or by simply creating a new object by
test1.testMethod(new Test1());
It should be noted that
test1.testMethod((String) null);
will again invoke the String method as this would create an object of type String.
Also,
test1.testMethod((int) null);
and
test1.testMethod((boolean) null);
will give a compile time error since boolean and int do not accept null as a valid value and as int!=Integer and boolean!=Boolean.
Integer and Boolean type cast to Objects of type int and boolean.

Related

Invoking the default constructor (in Java) in a class that only has a defined constructor that requires parameters

Please tell me if I have the proper understanding of the following code:
public class Test {
public static void main(String[] args) {
A a = new A();
a.print();
}
}
class A {
String s;
A(String s) {
this.s = s;
}
void print() {
System.out.println(s);
}
}
The line “A a = new A();” invokes the class/constructor to create a new object with reference variable “a”. Class A has a defined constructor that requires a string argument, thus it does not have the default constructor. This means that the instantiation without any string arguments causes a compiler error.
If I were to add a string argument into the instantiation, e.g. A a = new A("goldfish"); the program would compile and run.
I am not sure if I have used the right vocabulary for this, so feel free to correct anything that is inaccurate/confusing. Thanks!
Your understanding is pretty much correct. The one thing that I would change is "create a new object" to "create a new instance of A" with a reference to a java.lang.String in parameter s. In this case the constructor assigns that parameter to a field, but it can do something else with it entirely (such as use it to calculate a different value for some field).
What you wrote is roughly correct.
To be more precise: "invokes the class/constructor" is not entirely correct. A a = new A(); intends to invoke the constructor (invoking a class doesn't mean anything).
Though constructors are not methods, you can think of them a bit like methods: if your class has defined a method like so :
public void myMethod(String s) { ... }
Then trying to call myMethod() without any argument would fail. It's the same here.

Passing NULL to Overloading while checking Specificity in two Cases [duplicate]

If I write this line in Java:
JOptionPane.showInputDialog(null, "Write something");
Which method will be called?
showInputDialog(Component parent, Object message)
showInputDialog(Object message, Object initialSelectionValue)
I can test it. But in other cases similar to this, I want to know what happens.
The most specific method will be called - in this case
showInputDialog(Component parent, Object message)
This generally comes under the "Determine Method Signature" step of overload resolution in the spec (15.12.2), and in particular "Choosing the Most Specific Method".
Without getting into the details (which you can read just as well in the spec as here), the introduction gives a good summary:
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.
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.
In your particular case the more specific method will be called. In general, though, there are some cases where the method signature can be ambiguous. Consider the following:
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.testNullArgument(null);
}
private void testNullArgument( Object o )
{
System.out.println("An Object was passed...");
}
private void testNullArgument( Integer i )
{
System.out.println("An Integer was passed...");
}
private void testNullArgument( String s )
{
System.out.println("A String was passed...");
}
}
In this case, the compiler can't decide between the method that takes an Integer and the method that takes a String. When I try to compile that, I get
reference to testNullArgument is ambiguous, both method testNullArgument(java.lang.Integer) in testnullargument.Main and method testNullArgument(java.lang.String) in testnullargument.Main match
Neither. You'll get a compiler error asking you to clarify what method you want to call. You can do so by explicitly casting the first argument:
showInputDialog((Object) null, "Write something");
or
showInputDialog((Component) null, "Write something");
Update I should have known - never doubt Jon Skeet. The problem I've referred to above only occurs when it's impossible to determine which method is more specific. Here's a test case:
public class Test {
public void doSomething(String arg1, Object arg2) {
System.out.println("String, Object");
}
public void doSomething(Object arg1, String arg2) {
System.out.println("Object, String");
}
public static void main(String[] args) {
Test test = new Test();
test.doSomething(null, null);
}
}
The above will give a compiler error.

why this code does not give compilation error? [duplicate]

I came across this question in a quiz,
public class MoneyCalc {
public void method(Object o) {
System.out.println("Object Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
The output of this program is "String Version". But I was not able to understand why passing a null to an overloaded method chose the string version. Is null a String variable pointing to nothing ?
However when the code is changed to,
public class MoneyCalc {
public void method(StringBuffer sb) {
System.out.println("StringBuffer Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
it gives a compile error saying "The method method(StringBuffer) is ambiguous for the type MoneyCalc"
Is null a String variable pointing to nothing ?
A null reference can be converted to an expression of any class type. So in the case of String, this is fine:
String x = null;
The String overload here is chosen because the Java compiler picks the most specific overload, as per section 15.12.2.5 of the JLS. In particular:
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.
In your second case, both methods are still applicable, but neither String nor StringBuffer is more specific than the other, therefore neither method is more specific than the other, hence the compiler error.
Additionally, the JLS 3.10.7 also declares that "null" is a literal value of the "null type". Therefore there exists a type called "null".
Later, the JLS 4.1 states that there exists a null type of which is impossible to declare variables, but you can use it through the null literal only. Later it says:
The null reference can always undergo a widening reference conversion
to any reference type.
Why the compiler chooses to widen it to String might well be explained in Jon's answer.
You can assign a string to a null value so it is valid and the order for java and most programming languages is fit to the closest type and then to object.
To answer the question in the title: null is neither a String nor an Object, but a reference to either can be assigned to null.
I'm actually surprised this code even compiles. I tried something similar previously and I got a compiler error saying that the call was ambiguous.
However, in this case, it seems like the compiler is choosing the method which is lowest on the food chain. It's assuming that you want the least generic version of the method in order to help you out.
I'll have to see if I can dig up the example where I got a compiler error in this (seemingly) exact same scenario, though...]
EDIT: I see. In the version I made, I had two overloaded methods accepting a String and an Integer. In this scenario, there is no "most specific" parameter (as in Object and String), so it can't choose between them, unlike in your code.
Very cool question!
As String type is more specific than Object type. Let's say you add one more method that takes an Integer type.
public void method(Integer i) {
System.out.println("Integer Version");
}
Then you will get a compiler error saying that the call is ambiguous. As now we two equally specific methods with same precedence.
Java compiler gives most derived class type to assign null.
Here is the example to understand it :
class A{
public void methodA(){
System.out.println("Hello methodA");
}
}
class B extends A{
public void methodB(){
System.out.println("Hello methodB");
}
}
class C{
public void methodC(){
System.out.println("Hello methodC");
}
}
public class MyTest {
public static void fun(B Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
output: B Class.
on the other hand:
public class MyTest {
public static void fun(C Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
Result : The method fun(C) is ambiguous for the type MyTest
Hope it will help to understand this case better.
Source: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
Concept: Most specific method
Explanation: 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. Try casting the null on to specific type and the method you wish will be automatically called.
I would say neither. NULL is a state not a value. Check out this link for more info on this (the article applies to SQL, but I think it helps with your question as well).

Does a method's signature in Java include its return type?

Does the method signature in a Java class/interface include its return type?
Example:
Does Java know the difference between those two methods:
public class Foo {
public int myMethod(int param) {}
public char myMethod(int param) {}
}
Or is it maybe only the method name and parameters list that matter?
Quoting from Oracle Docs:
Definition: Two of the components of a method declaration comprise the method signature—the method's name and the parameter types.
Since the question was edited to include this example:
public class Foo {
public int myMethod(int param) {}
public char myMethod(int param) {}
}
No, the compiler won't know the difference, as their signature: myMethod(int param) is the same. The second line:
public char myMethod(int param) {}
will give you can error: method is already defined in class, which further confirms the above statement.
Is class method signature in Java includes return type ?
In Java, it doesn't but in this JVM it does which can lead to obvious confusion.
Is interface method signature in Java includes return type ?
The same as for class methods.
Or only method name and parameters list ?
Method name and parameter types for Java. For example, the parameter annotations and names don't matter.
At bytecode level, "return type" is part of method signature. Consider this
public class Test1 {
public Test1 clone() throws CloneNotSupportedException {
return (Test1) super.clone();
}
}
in bytecode there are 2 clone() methods
public clone()LTest1; throws java/lang/CloneNotSupportedException
public clone()Ljava/lang/Object; throws java/lang/CloneNotSupportedException
they differ only by return type.
No not in Java. Method name and parameter list is only for method signature. Return type doesn't include.
In JAVA and many other languages, you can call a method without a variable to hold the return value. If return type is part of a method signature, there is no way to know which method will be called when calling without specifying variable holding return value.
Java Language Spec says
Two methods have the same signature if they have the same name and argument types.
thus No, return type is not part of method signature.
Bro, In java, we use to call methods by their name and their parameters only to use them in our code, like
myMethod(20, 40)
so, JAVA only searches for similar stuff matching in their corresponding declaration (name + param), this is why method signature only includes method's name and parameters. :)
The method signature is the name and parameter list only.
no, in Java the method signature doesn't includes the return type, but the declaration does.
public String getString(String myString)
^access modifier ^return type ^name ^parameter type and name
edited based on feedback below :)
Return type doesn't include in method signature.Only method name and Parameters are defined as method signature.
Reffer : Oracle Docs 'Defining Methods'
THE METHOD SIGNATURE INCLUDES THE RETURN TYPE.
The compiler ignores it when has to check for duplicates. For Java is illegal to have two methods with the signature differing only by the return type.
Try that:
public class Called {
public String aMethod() {
return "";
}
}
public class Caller {
public static void main(String[] main) {
aMethod();
}
public static void aMethod() {
Called x = new Called();
x.aMethod();
}
}
Build the project, go to bin directory, copy the Caller.cass somewhere. Then change the called method:
public int aMethod() {
return 0;
}
Build the project, you will see that both Called.class and Caller.class have a new timestamp. Replace the Caller.class above and run the project. You'll have an exception:
java.lang.NoSuchMethodError: it.prova.Called.aMethod()Ljava/lang/String;
Using AspectJ (org.aspectj.lang.reflect.MethodSignature), it does have the return type
The method signature is only the method's name and parameters. But I believe your example will generate an error if they were to be in the same class. You can simply test it out on any ide and see that the compiler will throw an error
If you try to run the code you have mentioned on eclipse, you will have an answer as to what elements does java compiler looks for differentiating among java methods :
class Foo {
public int myMethod(int param) {
return param;}
public char *myMethod*(int param) { //this line throws an error
return param;
}
}
The error thrown is :
Duplicate method myMethod(int) in type Foo .

How is an overloaded method chosen when a parameter is the literal null value?

I came across this question in a quiz,
public class MoneyCalc {
public void method(Object o) {
System.out.println("Object Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
The output of this program is "String Version". But I was not able to understand why passing a null to an overloaded method chose the string version. Is null a String variable pointing to nothing ?
However when the code is changed to,
public class MoneyCalc {
public void method(StringBuffer sb) {
System.out.println("StringBuffer Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
it gives a compile error saying "The method method(StringBuffer) is ambiguous for the type MoneyCalc"
Is null a String variable pointing to nothing ?
A null reference can be converted to an expression of any class type. So in the case of String, this is fine:
String x = null;
The String overload here is chosen because the Java compiler picks the most specific overload, as per section 15.12.2.5 of the JLS. In particular:
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.
In your second case, both methods are still applicable, but neither String nor StringBuffer is more specific than the other, therefore neither method is more specific than the other, hence the compiler error.
Additionally, the JLS 3.10.7 also declares that "null" is a literal value of the "null type". Therefore there exists a type called "null".
Later, the JLS 4.1 states that there exists a null type of which is impossible to declare variables, but you can use it through the null literal only. Later it says:
The null reference can always undergo a widening reference conversion
to any reference type.
Why the compiler chooses to widen it to String might well be explained in Jon's answer.
You can assign a string to a null value so it is valid and the order for java and most programming languages is fit to the closest type and then to object.
To answer the question in the title: null is neither a String nor an Object, but a reference to either can be assigned to null.
I'm actually surprised this code even compiles. I tried something similar previously and I got a compiler error saying that the call was ambiguous.
However, in this case, it seems like the compiler is choosing the method which is lowest on the food chain. It's assuming that you want the least generic version of the method in order to help you out.
I'll have to see if I can dig up the example where I got a compiler error in this (seemingly) exact same scenario, though...]
EDIT: I see. In the version I made, I had two overloaded methods accepting a String and an Integer. In this scenario, there is no "most specific" parameter (as in Object and String), so it can't choose between them, unlike in your code.
Very cool question!
As String type is more specific than Object type. Let's say you add one more method that takes an Integer type.
public void method(Integer i) {
System.out.println("Integer Version");
}
Then you will get a compiler error saying that the call is ambiguous. As now we two equally specific methods with same precedence.
Java compiler gives most derived class type to assign null.
Here is the example to understand it :
class A{
public void methodA(){
System.out.println("Hello methodA");
}
}
class B extends A{
public void methodB(){
System.out.println("Hello methodB");
}
}
class C{
public void methodC(){
System.out.println("Hello methodC");
}
}
public class MyTest {
public static void fun(B Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
output: B Class.
on the other hand:
public class MyTest {
public static void fun(C Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
Result : The method fun(C) is ambiguous for the type MyTest
Hope it will help to understand this case better.
Source: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
Concept: Most specific method
Explanation: 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. Try casting the null on to specific type and the method you wish will be automatically called.
I would say neither. NULL is a state not a value. Check out this link for more info on this (the article applies to SQL, but I think it helps with your question as well).

Categories