what does "method1().method2().method3()" mean in java? - java

I know some basics of java language.
But I don't know some statements like this:
method1().method2().method3()
Two or three methods separated whit dots operator! I cannot understand it.
What does it mean? How can I use them? Do they process from left to right or reverse?
Does they return special values or not?
How can I understand I should some methods separate whit dot?
How can I create methods like this?

I will gave you a little example.
method1().method2().method3();
getYear().toString().trim();
first execute get year() which returns a Integer:
1995.toString().trim();
secound execute toString() method of integer class which returns an string:
"1995".trim();
at least the compiler would execute trim() method of string class.
the first method return a number then you use toString() method on this number and format it to a string. this will return a string and then you can use the trim() method of string class to trim() the string. you are executed the next method after you get the return from the method in front of.

That is chaining of method calls. THe object returned by method1() will call method2()
As an example,
public static String methodToReturnString() {
return "someString";
}
You call this using String subString = methodToReturnString().toLowerCase().substring(3);
This returns a String estring.
This is similar to the code as follows.
String s1 = methodToReturnString();
String s2 = s1.toLowerCase();
String s3 = s2.substring(3);
System.out.println(s3);
As for generating this s3 variable, we needed to store the return values of method in some variables which is not needed. Using method chaining, we have avoided variables s1, s2 here.

method1 returns object, which has method2 and then you can call method2, which returns object that has method3 and you call it.

Your statement will be interpreted as follows:
Invoke method1(). The return value will be some object.
Invoke method2() on the object returned by method1(). This method too must have a return value.
Invoke method3() on the object returned by method2().
You can rewrite this as:
SomeType value1 = method1();
SomeOtherType value2 = value1.method2();
value2.method3();

See... For example we might have
String s= "abcde";
String str = s.trim().subString(2);
1 --> trim() is called on "s".
2 --> subString() is called on the result of s.trim()

Method1 returns object1, which has method2 which returns object2, which has method3.
Object1 and object2 and current object can be identical, which is used in builder pattern.
Something like:
Student {
Semester lastFinishedSemester();
}
Semester {
Courses registeredCourses();
}
Courses {
void printCoursesAndGrades();
}
now if you are in one of student methods, you can call:
lastFinishedSemester().registeredCourses().printCoursesAndGrades();

obj.method1().method2().method3()
equals to
( ( obj.method1() ).method2() ).method3()
Important:
method1() must return an object that has method2()
method2() must return an object that has method3()
Source: Yosi Hendarsjah's answer in https://coderanch.com/t/398558/java/method-chaining

Related

String Buffer method "toString"

what happens when you call "toString" method without a string variable to collect value that is returned?
For eg: here are two code snippets I tired. the first one gives the correct answer, the second gives a wrong answer but it still compiles. If "toString" method is meant to return a value, shouldn't I get a compiler error for the second block of code?
StringBuffer sb=new StringBuffer(s); //s is a string input taken from user
sb.reverse();
String rev=sb.toString();
if(s.equals(rev)){
System.out.println("yes");
/*second try*/
StringBuffer sb=new StringBuffer(s);
sb.reverse();
sb.toString();//what is happening here?
if(s.equals(sb)){
System.out.println("yes");
It is simple to understand.
In the first case, the value is returned and is being referenced by a variable so that you can make use of that value later on.
In the second case, the value is returned just like before but it is not being referenced by any variable. Thus, the value simply goes into waste and can not be used or manipulated later on.
sb.toString();//what is happening here?
You are converting the StringBuilder object to String which is good but you are not storing the return value to a String type and using it later in your equals call. You should do it the following way:
String reversedString = sb.toString();
if(s.equals(reversedString )){
Or simply
if(s.equals(sb.toString())){
Right now you are comparing s with sb using the equals method of String class. This method returns false if the object passed in as an argument is not an instance of String class. Since StringBuilder object sb is not an instance of String, the equals method returns false.
toString will return whatever the toString method of the object returns.
Try System.out.println(sb.toString); to see what it is returning.
StringBuffer#toString() returns a string, if you don't place that returned value in a variable then nothings happens and the information you've requested is gone.
.toString() is a method that returns a string, it does not convert that StringBuffer into a string.
if(s.equals(sb.toString())) would work because it is comparing s to the value of sb as a string, even though it is not assigning the value to variable.
In Java you don't have to check or store any return value.
sb.toString() is executed and the return value is truncated.
Please note that the method must be executed, because there might be side effects. To test it out, you might implement in your class:
#Override
public String toString() {
System.out.println("toStringTest");
return super.toString();
}
"toStringTest" will be put out!

Java Method Confusion

In Java, when for example you say string1.compareTo(string2), how is the compareTo method accessing the string1. I see the method takes in the second string but how does it compare it to the first if it is not getting passed along?
compareTo() is a member function of Class String, this means that for invoking this function you need an Object of Type String. So when you say string1.compareTo(string2) , this means that you are invoking compareTo() function on the String object 'string1' and passing 'string2' as the argument.
I think this little 'illustration' could help you
Class String {
public int CompareTo(String string2)
{
if (this==string2) return 1; //The == is completely wrong here but it gives you an idea on how it works
else return 0;
}
}
When you call string1.CompareTo(string2); in the method, this will reference the object itself, so here it references string1

How does System.out.print() work?

I have worked with Java for a quite a long time, and I was wondering how the function System.out.print() works.
Here is my doubt:
Being a function, it has a declaration somewhere in the io package. But how did Java developers do that, since this function can take in any number of arguments and any argument types no matter how they are arranged? e.g:
System.out.print("Hello World");
System.out.print("My name is" + foo);
System.out.print("Sum of " + a + "and " + b + "is " + c);
System.out.print("Total USD is " + usd);
No matter what is the datatype of variables a, b, c, usd, foo or how they are passed, System.out.print() never throws an error.
For me, I have never worked on any project where the requirement was like this. Provided, if I get a requirement like this, I really don't know how to solve it.
Can anyone explain to me how it's done?
System.out is just an instance of PrintStream. You can check its JavaDoc. Its variability is based on method overloading (multiple methods with the same name, but with different parameters).
This print stream is sending its output to so called standard output.
In your question you mention a technique called variadic functions (or varargs). Unfortunately that is not supported by PrintStream#print, so you must be mistaking this with something else. However it is very easy to implement these in Java. Just check the documentation.
And if you are curious how Java knows how to concatenate non-string variables "foo" + 1 + true + myObj, it is mainly responsibility of a Java compiler.
When there is no variable involved in the concatenation, the compiler simply concatenates the string. When there is a variable involved, the concatenation is translated into StringBuilder#append chain. There is no concatenation instruction in the resulting byte code; i.e. the + operator (when talking about string concatenation) is resolved during the compilation.
All types in Java can be converted to string (int via methods in Integer class, boolean via methods in Boolean class, objects via their own #toString, ...). You can check StringBuilder's source code if you are interested.
UPDATE: I was curious myself and checked (using javap) what my example System.out.println("foo" + 1 + true + myObj) compiles into. The result:
System.out.println(new StringBuilder("foo1true").append(myObj).toString());
Even though it look as if System.put.print...() take a variable number of arguments it doesn't. If you look closely, the string is simply concatenated and you can do the same with any string. The only thing that happens is, that the objects you are passing in, are implicitily converted to a string by java calling the toString() method.
If you try to do this it will fail:
int i = 0;
String s = i;
System.out.println(s);
Reason is, because here the implicit conversion is not done.
However if you change it to
int i = 0;
String s = "" + i;
System.out.println(s);
It works and this is what happens when using System.put.print...() as well.
If you want to implement a variable number of arguments in java to mimimc something like C printf you can declare it like this:
public void t(String s, String ... args)
{
String val = args[1];
}
What happens here is that an array of Strings is passed in, with the length of the provided arguments. Here Java can do the type checking for you.
If you want truly a printf then you have to do it like this:
public void t(String s, Object ... args)
{
String val = args[1].toString();
}
Then would you have to cast or interpret the arguments accordingly.
It is a very sensitive point to understand how System.out.print works.
If the first element is String then plus(+) operator works as String concate operator. If the first element is integer plus(+) operator works as mathematical operator.
public static void main(String args[]) {
System.out.println("String" + 8 + 8); //String88
System.out.println(8 + 8+ "String"); //16String
}
Evidently, the compiler was made in a confusing way although the compiler developers thought they added some smartness. The true smartness they should really add is to look entire argument and interpret + operator consistently. For example, System.out.println(1+2+"hello"+3+4); should output 3hello7 instead of 3hello34
I think you are confused with the printf(String format, Object... args) method. The first argument is the format string, which is mandatory, rest you can pass an arbitrary number of Objects.
There is no such overload for both the print() and println() methods.
Its all about Method Overloading.
There are individual methods for each data type in println() method
If you pass object :
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
If you pass Primitive type:
corresponding primitive type method calls
if you pass String :
corresponding println(String x) method calls
You can convert anything to a String as long as you choose what to print. The requirement was quite simple since Objet.toString() can return a default dumb string: package.classname + # + object number.
If your print method should return an XML or JSON serialization, the basic result of toString() wouldn't be acceptable. Even though the method succeed.
Here is a simple example to show that Java can be dumb
public class MockTest{
String field1;
String field2;
public MockTest(String field1,String field2){
this.field1=field1;
this.field2=field2;
}
}
System.out.println(new MockTest("a","b");
will print something package.Mocktest#3254487 ! Even though you only have two String members and this could be implemented to print
Mocktest#3254487{"field1":"a","field2":"b"}
(or pretty much how it appears in the debbuger)
#ikis, firstly as #Devolus said these are not multiple aruements passed to print(). Indeed all these arguments passed get
concatenated to form a single String. So print() does not teakes multiple arguements (a. k. a. var-args). Now the concept that remains to discuss is how print() prints any type of the arguement passed
to it.
To explain this - toString() is the secret:
System is a class, with a static field out, of type PrintStream. So you're calling the println(Object x) method of a
PrintStream.
It is implemented like this:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
As wee see, it's calling the String.valueOf(Object) method. This is implemented as follows:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
And here you see, that toString() is called.
So whatever is returned from the toString() method of that class, same gets printed.
And as we know the toString() is in Object class and thus inherits a default iplementation from Object.
ex: Remember when we have a class whose toString() we override and then we pass that ref variable to print, what do you see printed? - It's what we return from the toString().
The scenarios that you have mentioned are not of overloading, you are just concatenating different variables with a String.
System.out.print("Hello World");
System.out.print("My name is" + foo);
System.out.print("Sum of " + a + "and " + b + "is " + c);
System.out.print("Total USD is " + usd);
in all of these cases, you are only calling print(String s) because when something is concatenated with a string it gets converted to a String by calling the toString() of that object, and primitives are directly concatenated.
However if you want to know of different signatures then yes print() is overloaded for various arguments.

How an object will call toString method implicitly?

If I am printing an object of the class then it is printing the toString() method implementation even I am not writing the toString() method so what are the implementation,how it is calling toString() internally?
You're not explicitly calling toString(), but implicitly you are:
See:
System.out.println(foo); // foo is a non primitive variable
System is a class, with a static field out, of type PrintStream. So you're calling the println(Object) method of a PrintStream.
It is implemented like this:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
As we see, it's calling the String.valueOf(Object) method.
This is implemented as follows:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
And here you see, that toString() is called.
Every object in Java IS-A(n) Object as well. Hence, if a toString() implementation has not been provided by a class the default Object.toString() gets invoked automatically.
Object.toString()'s default implementation simply prints the object's class name followed by the object's hash code which isn't very helpful. So, one should usually override toString() to provide a more meaningful String representation of an object's runtime state.
even I am not writing the toString() method so what are the implementation,how it is calling toString() internally?
toString() is one of the few methods (like equals(), hashCode() etc.) that gets called implicitly under certain programmatic situations like (just naming a few)
printing an object using println()
printing a Collection of objects (toString() is invoked on all the elements)
concatenation with a String (like strObj = "My obj as string is " + myObj;)
Everything inherits from Object, so the toString on Object will be called if you have not defined one.
toString() method is present in Object class, so when u put obj in System.out.println(obj);, impliciyly it will call toString() present in Object class since every user created class will implicitly inherits Object class so as ur newly created class, that means that toString() is available in ur class so it will print something like for example: "PkgNamePackage.Classname#12cf4"
However if u explicitely override toString method and give ur own implementation then it will written the string what ever u give in Overriden tostring method();
ex:
public class DogArray {
#Override
public String toString() {
return "Im the newly created Object";
}
public static void main(String args[]) {
DogArray d1 = new DogArray();
System.out.println(d1);
}
}
output: Im the newly created Object
In java object class is super class to the each and every class.whenever your passing parameter to the system.out.println internally object class to string method will be excuted.it returns class name#reference value given but as per our application requirement object class to string method will override in collection and string class.it returns their content.

Custom 'String' Class

I'm trying to figure out how java classes work.
When I create a StringBuilder:
StringBuilder testString = new StringBuilder("Hello World!);
If I want to, say, get the value that testSting holds a reference to, I can simply call it like: System.out.println(testString);
This is cool behavior, but I'm unsure how to replicate it in classes that I make.
For instance, if I were to try and re-implement my own version of StringBuilder, the approach I would take (as a beginner), would be this:
class MyBuilder {
char[] string;
public MyBuilder(String s) {
string = new char[s.length()];
string = s.toCharArray();
}
So, to make the string an array I had to store it in a data field of the class. But then, to access this in my code, I can't print it by simply calling the variable name. I would have to use .property syntax. Thus, to duplicate the above example, I would have to type System.out.println(testString.value); Which isn't nearly as pretty.
How do you make a class such that it behaves like String or StringBuilder and returns its value without manually accessing the data fields?
Implement a toString method.
toString is a method on Object, so every java object inherits one. The default implementation that you inherit is only useful for getting the class type, and for distinguishing one object from another; the format is: ClassName#HashCode. There are no details unique to your implementation.
In your own classes, to get the description that you want you'll need to override the toString method, so that in contexts where a String is expected, e.g. when you call System.out.println(myObject.toString());, your own format is used.
It's often a good idea to do this, for a more readable description of your object. You can always call super.toString to include the output from the default - ClassName#HashCode - in your own output.
You can override Object.toString() in your object MyBuilder. System.out.println calls on this method for every object used. For example here, you could use:
#Override
public String toString() {
return Arrays.toString(string);
}
Overwrite the toString-Method
private String value;
public MyClass(String value) {
this.value = value;
}
public String toString() {
return value;
}

Categories