What actually happens in the compiler in this case - java

I have a small question, given the following snippet:
StringBuilder stringBuild = new StringBuilder(3);
stringBuild.append("hello");
System.out.println(stringBuild+2); // if I omit the (+2) bit hence only stringBUild it works
Does it call automatically toString() on object only in some circumstances? (circumstances: either no operation at all or a previous string contatanation)

The compiler never calls toString() on a method argument implicitly.
What you are probably thinking of, is that there is an overload of System.out.println which takes an Object (rather than a String) - this is the method that the compiler would link to. And this particular implementation of the method calls toString on the Object passed in (at runtime). That's just code though, it's nothing to do with compiler behaviour.
So passing in an Object to System.out.println "works". Passing in stringBuild+2 simply doesn't compile - there's no + operator on StringBuilder which takes an int. (And you can't create one yourself as Java doesn't allow for operator overloading.)
As ADTC and tom point out, there is implicit String conversion with the second argument to string concatenation (the + operator for strings). So while stringBuild doesn't have a + operator, stringBuild.toString() would, and you could call stringBuild.toString()+2.

Related

Why is the order of parameters considered part of a method's signature in context of method overloading?

In this code ...
public class Person {
public void walk(String alpha, int beta) {}
public void walk(int beta, String alpha) {}
}
... I am just changing the order of parameters, but it is still considered as method overloading, i.e. static binding at compile time. My questions are:
Why order is considered to be part of a method's signature in Java?
What are the advantages? From my POV I do not see the exact advantage in doing so.
Because "having lunch first and jogging afterwards", and "jogging first and having launch afterwards", are two different patterns, even though they only differ in order.
In Java, we have a concept of Method Overloading, which says, that in one class, you are able to define methods with the same name, as long as their signatures will be different.
Now let's reformulate above "jogging/lunch" example, into more formal and Java-related concepts:
When you have overloaded methods, JVM needs some way to understand which particular overloaded method to invoke, using the name that identifies more than one methods; and it knows that, thanks to the type, number, and the order of the method parameters.
Type, only, is not enough information, because if Java dismisses the order for matching parameters and their respective arguments, it will not be clear which particular method to call.
Imagine you define foo(int a, char b) and foo(char a, int b), and you somewhere, invoke .foo([...]). How do you think, based on what compiler should decide which method call to compile for this code? (compiler won't let you through, if you violate signature);
Furthermore - how the JVM should do the binding, later, at runtime, when the foo is invoked, but there are, at least, two methods, defined with the same name?
For this, methods have signatures, where the order of parameters, exhibiting distinct patterns, gives the ability, to Java machine, to proceed with a correct and appropriate bindings and calls.
Also, think about varargs, in the hypothetical scenario, where order of the parameters does not matter.
Do you think:
foo(String... a, String b)
and
foo(String b, String... a)
will be same?
If you do, you are wrong.
In the layman's terms, it gets difficult to parse the input pattern - how many of the input string literals, method of the first signature, should consider to accept, as an array argument, in its first parameter (only first literal? first two ones?.. how many? where the array ends?), and which string argument, particularly, should be accepted into the second parameter (for a more in depth explanation, see this); therefore, you will have a compile time error:
error: varargs parameter must be the last parameter
While in the second case, disregarding of how many strings you will call this method with, first argument will be always bound to the first parameter, and the rest will be constituting an array, passed as an argument, into the second parameter.
The order of the parameters make a difference because it is a different signature. Imagine you had a human signature and altered the order of the letters, it would no longer be the same signature.
If we take my Username as an example, RStevoUK is totally different to UKRStevo.
Are there any advantages in the case that you are presenting? No.
I wouldn't advise having a method with the same name and the same parameters but just shuffled around because it would make no sense to do that. All that you would achieve is the possibility of calling the wrong method (if they both had a different method body) and confusion, like you have suggested.

how two links are linked together in Java built-in libraries?

for example in Scanner we have
obj.next()
but we can call another method after next()
obj.next().charAt(0)
how can I make similar thing for example
obj.getName().toLowerCase()
What you have observed – with examples like obj.getName().toLowerCase() – is that when the return type of a method call is itself some other object, then you can immediately call a new method on that newly returned object.
Here's another example: String s = String.class.getName().toLowerCase();. This example could be rewritten like so:
Class<String> stringClass = String.class;
String name = stringClass.getName();
String s = name.toLowerCase();
Both of the one-line and multi-line version of this code result in a String object, referenced by s, which contains the value "java.lang.string".
Note that chaining method calls together is not possible if the return type isn't an object, such as an integer value. For example, here's a method call that results in a primitive long value, which isn't an object, so you can't call any methods on that result – that is, something like millis.hashCode() isn't possible.
long millis = System.currentTimeMillis();
To address your primary question finally: you can create this same behavior by creating methods that return objects instead of primitives (int, long, byte, etc.).

How is this static method called on a instance value wrong?

How is this legal
System.out.println("".valueOf(1121997));
And this is illegal
System.out.println(1.valueOf("1121997"));
"" is a string literal, and the java compiler makes sure that a String object will be automatically created for each string literal that you use in your program. So, since "" is an object, it has methods like valueOf().
On the other hand, 1 is an int literal, so there is no object created for it; it is just a primitive. Primitives do not have methods in java.
Because "" is a String. String Class has a valueOf method, so you can call it.
For your old question,
System.out.println( 1.valueOf("1121997"));
Here 1 is primitive integer value and not Integer Wrapper class. You can not call method on primitive data types.
For your updated Question,
System.out.println((Integer) 1.valueOf("1121997"));
Here you need to wrap (Integer)1 with additional ().
System.out.println(((Integer) 1).valueOf("1121997"));
Also valueOf() is a static method. It is not a good practice to call it with instance. You should call it directly with class name like
Integer.valueOf("1121997");
"" is a reference to a String Object, therefore has methods like length, valueOf, etc.
1 is an integer literal. It is a primitive data type, therefore you can't call methods on it.

what does this scala code do?

I am still new to Scala.
I found this code inside Spray framework.
I am trying to understand what the method signature means:
/**
* Completes the request using the given arguments.
*/
def complete: (⇒ ToResponseMarshallable) ⇒ StandardRoute = marshallable ⇒ new StandardRoute {
def apply(ctx: RequestContext): Unit = ctx.complete(marshallable)
}
What does the => operator do here? I thought it was used for creating a closure?
What is the assignment to marshallable being done here? why is it done outside the brackets?
A java version of this code would be nice to see.
So.
The first thing to notice is that complete is declared with a def, so it is a method, but the parentheses that look like they might be method arguments come after the colon :.
So they are not in fact method arguments. complete is a no-argument method!
Then what's up with the parens after the colon?
(⇒ ToResponseMarshallable) ⇒ StandardRoute is the return type of the no-arg method complete. The function complete returns a function that accepts an expression of type ToResponseMarshallable and returns a StandardRoute.
OK. But then what's up with the arrow before ToResponseMarshallable in the function signature (⇒ ToResponseMarshallable) ⇒ StandardRoute?
In a function signature, an ⇒ prior to the type name signifies a "call-by-name" argument. Following java, Scala by default evaluates all expressions in an argument list, and then evaluates the method body, substituting the evaluated values for the variable. But Scala also supports call-by-name semantics, in which an expression is substituted unevaluated into a function, and re-executed every time that it is named. complete returns a function whose single argument has call-by-name semantics.
Following the equals sign is just the implementation of this method. The expression beginning with marshallable ⇒ is an anonymous function, or function literal, or lambda (all names for basically the same thing). marshallable ⇒ "hello" would be a function that accepts (by name) a ToResponseMarshallable and returns the String "hello". But we need a method that accepts a ToResponseMarshallable (by name) and retuns a StandardRoute. So we have marshallable ⇒<expression that evaluates to a StandardRoute>
That <expression that evaluates to a StandardRoute> is just an anonymous inner class, an implementation of StandardRoute that overrides its apply method.
And we're done! We (hopefully) understand all the pieces, and what this declaration means.

toString: When is it used?

I have a class
class Configuration {
// various stuff
#Override
public String toString() {
// assemble outString
return outString;
}
}
I also have another class
class Log {
public static void d(String format, Object... d) {
// print the format using d
}
}
The Log class works perfectly fine, I use it all the time. Now when I do this:
Configuration config = getConfiguration();
Log.d(config);
I get the compiler error The method d(String, Object...) in the type Log is not applicable for the arguments (Configuration). I can solve this:
Log.d("" + config); // solution 1
Log.d(config.toString()); // solution 2
My problem: How is this different? In the first solution, the compiler notices that it has to concatenate two Strings, but the second one is a Configuration. So Configuration#toString() is called and everything is fine. In the compiler error case the compiler sees that a String is needed, but a Configuration is given. Basically the same problem.
Needed: String
Given: Configuration
How are these cases different and why is toString not called?
While designing the language, someone decided that when a programmer appends an arbitrary object to a string using the + operator, they definitely want a String, so implicitly calling toString() makes sense.
But if you call an arbitrary method that takes a String with something else, that is simply a type error, exactly what all that static typing is supposed to prevent.
The line
"" + config
gets translated to something like
StringBuilder sb = new StringBuilder("");
sb.append(config);
where the second line calls
StringBuilder.append(Object obj);
This method calls obj.toString() to get the String representation of the object.
On the other hand, the first parameter of Log.d must be a String, and Java doesn't automatically call toString() to cast everything to a String in that case.
One of the common use of toString(), is print() and println() methods of PrintStream, as in:
System.out.print(object);
System.out.println(object);
Basically, these two methods will call toString() on the passed object. This is one of the Polymorphism's benefits.
Nice Question...
But,
Compiler does not call a method to match formal parameters. it simply tries to cast the objects if possible.
But when you use the "+" operator the compiler executes the toString() method of its arguments (in case they are objects) by default.
In one case you are passing an object argument to an operator which expects objects.
In the earlier case you are passing an object argument to a function which expects string.
Basically function/operator signature is different.
It is almost incidental [in the context of this question] that .tostring called when + is applied. It takes an object and does something.
For all you know, you might be passing in object when string is required by mistake. So it can't blindly do .tostring()
You are passing Configuration class object argument in case 1 but in the case 2 , you are passing string argument . so no error occures.

Categories