What is the explanation of this java code? - java

I have the following code :
public class Main {
public void method(Object o)
{
System.out.println("Object Version");
}
public void method(String s)
{
System.out.println("String Version");
}
public static void main(String args[])
{
Main question = new Main();
question.method(null);//1
}
}
why is the result is "String Version" ? and why there is a compiler error if the first method takes a StringBuffer object ?
Another case : if the first method takes a StringBuffer object and I write question.method("word");the result will be "String Version" . Why ? why there is no compiler error ?

The JAVA spec says that in cases like this, the most specific function will be called. Since String is a sub type of Object - the second method will be called.
If you change Object to StringBuffer - there is no specific method since StringBuffer is not a sub type of String and vice versa. In this case the compiler does not know which method to call - hence the error.

When looking at the other case :
package com.snamellit;
public class Main {
public void method(Object o) {
System.out.println("Object Version");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
Main question = new Main();
question.method("word");
}
}
If the first method tqkes a StringBuffer and the second a String, there is no confusion possible as "word" is a String and not a StringBuffer.
In Java the identity of a function/method is dependent on 3 things : the name, the type pf the parameters (aka the argument signature) and the classloader. Since both types have a different argument signature the compiler can easily choose the right one and does not raise an error.

Related

Unexpected overloaded method compiler selection with null parameter [duplicate]

This question already has answers here:
How to do method overloading for null argument?
(7 answers)
Closed 6 years ago.
I am very surprised why output is very much different from what I am expecting , I have two overloaded methods, one having one String and the other an Object as parameter, while calling this method with null parameter, output is just printing
"String"
and not calling method having object as parameter.
Why does Java selects the method having String as parameter, how java determines which overloaded method to call ?
class TestingClass {
public void test(String s) {
System.out.println("String");
}
public void test(Object o) {
System.out.println("Object");
}
public static void main(String[] args) {
TestingClass q = new TestingClass();
q.test(null);
}
}
There is no overriding in this code, only method overloading. When the compiler has to choose which of the two test methods to execute (since null can be passed to both), it chooses the one with the more specific argument type - test(String s) - String is more specific than Object since it is a sub-class of Object.
The other method can be called using :
q.test((Object) null);
Without adding a possible new answer, let me suggest you to extend your code like following,
public class Overload {
public static void main(String[] args) {
new Overload().test(null);
}
public void test(String s) {
System.out.println("String");
}
public void test(Object o) {
System.out.println("Object");
}
public void test(Integer s) {
System.out.println("Integer");
}
}
Comment out any one of Object or Integer version any see it for yourself. The answer being already provided by others.

Method overloading with dynamic casting

I'm looking into the method overloading of Java.
Take the next sample :
public static void main(String[] args) {
Object object = "some String";
System.out.println(object.getClass().getSimpleName());
System.out.println(belongsToAllowedTypes(object.getClass().cast(object)));
String string = "another String";
System.out.println(belongsToAllowedTypes(string));
}
public static boolean belongsToAllowedTypes(Object value) {
return false;
}
public static boolean belongsToAllowedTypes(String value) {
return true;
}
I'm expecting an output like :
String
True
True
Just because I get the String class and cast the Object to that class before I invoke the method.
But no luck, I'm getting false in the second println.
So it's still processed as an Object (however the class is String)
If I change it to :
System.out.println(belongsToAllowedTypes(String.class.cast(object)));
I do get a True.
Can anyone explain this behavior?
The method to call is determined at compile time. So with object having type Object the type of
object.getClass().cast(object))
at compile time is an Object independent of the dynamic content of object.

Call seems ambiguous, but runs perfectly with unexpected output

Please see this Java Class
class Demo
{
public static void a(String s)
{
System.out.println("string called");
}
public static void a(Object a)
{
System.out.println("Object called");
}
public static void main(String...asrgs)
{
a(null);
}
}
The output of this code is "string called" but I am not able to understand that how compiler is able to resolve between Object and String.
Moreover, examine this code fragment
class Demo
{
public static void a(String s)
{
System.out.println("string called");
}
public static void a(Integer n)
{
System.out.println("number called");
}
public static void a(Object a)
{
System.out.println("Object called");
}
public static void main(String...asrgs)
{
a(null);
}
}
Here we get a compile time error related to ambiguous call (which is quite obvious).
Any good explanations for this ?
The answer lies in §15.12.2 of the JLS:
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is the one used at run time to perform the method dispatch.
(my emphasis)
...and §15.12.2.5, which the section above refers to, which has the full details of specificity rules, but also this handy summary:
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 error.
In your first example, a(String) is more specific than a(Object), so the compiler knows which one to use and is happy. In your second example, both a(String) and a(Integer) are more specific than a(Object), but either is applicable to null and they're in separate lineages (String is String > Object, Integer is Integer > Number > Object), creating the ambiguity the compiler complains about.
If they were in the same lineage, there'd be no ambiguity, because there'd be a single applicable most specific option. For example:
class Base {
}
class Child extends Base {
}
class GrandChild extends Child {
}
public class Example {
public static final void main(String[] args) {
a(null);
}
public static void a(Base b) {
System.out.println("Base");
}
public static void a(Child b) {
System.out.println("Child");
}
public static void a(GrandChild b) {
System.out.println("GrandChild");
}
}
That prints "GrandChild", because while both a(Child) and a(GrandChild) are more specific than a(Object), a(GrandChild) is more specific than a(Child).

Giving the parameter System.out::println to a method

I forgot a concept that I used and can't remember it.
For the context, I used to have a method like toString() which had a parameter. This parameters allowed me to call my method like myMethod(System.out::println) to print it on the screen, but also to print it in a file with the same syntax.
Does anyone know what can be this parameter? the concept?
I think it's kind of a FunctionalInterface but I don't know what it is.
This is called method reference and applies when you know what method you want to call, provided the method already exist.
From the tutorial :
Because this lambda expression invokes an existing method, you can use
a method reference instead of a lambda expression:
Arrays.sort(rosterAsArray, Person::compareByAge);
Available since Java-8.
An exemple using what you want:
public static void function(String s, Consumer<String> f) {
f.accept(s);
}
public static void main(String args[]) {
String test1 = "test";
String test2 = "test2";
function(test1, System.out::println);
function(test2, System.out::println);
function(test1, System.out::print);
function(test2, System.out::print);
}
This goes well with java 8 functional interface:
#FunctionalInterface
static interface MyPrinter {
public void println(String line);
}
static void myMethod(MyPrinter mp) {
mp.println("Hello wolrd");
}
...
public static void main(String[] args) throws IOException {
myMethod(System.out::println);
PrintWriter pw = new PrintWriter("myFile.txt");
myMethod(pw::println);
pw.close(); //never forget to close file output streams!
//EDIT: note that you can of course store your MyPrinter in a variable:
MyPrinter mp = System.err::println;
myMethod(mp);
}
Would this work for you?
public class C {
static void myMethod(java.io.PrintStream p) {
p.println("Hello!");
}
public static void main(String args[]) {
myMethod(System.out);
}
}
Unfortunately you can't pass System.out.println directly, because in Java methods (before Java 8) are not first-class objects. All you can do with a method is calling it. As a workaround, you can introduce an interface and create an adapter class.

Couldn’t understand the output of this code? [duplicate]

This question already has answers here:
Strange Java null behavior in Method Overloading [duplicate]
(4 answers)
Closed 9 years ago.
public class Test {
public void method(String param)
{
System.out.println("String version");
}
public void method(StringBuffer param)
{
System.out.println("String Buffer");
}
public static void main(String args[])
{
Test test=new Test();
test.method(null);
}
}
This code result is compilation error says “reference to method is ambiguous”
public class Test
{
public void method1(Object param)
{
System.out.println("Object Version ");
}
public void method1(String param)
{
System.out.println("String Version ");
}
public static void main(String[] args)
{
Test test=new Test();
test.method1(null);
}
}
This code result is “String Version”
Actually I can’t understand the result of second piece of code. Why don’t both piece of code has the same result
In first case,
null is a subtype of every other reference type.
So, compiler finds ambiguity in deciding which method to call..
In second case, it finds more specific object for null which happens to be String. Hence it calls method1 and prints String Version

Categories