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!
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
I do not understand why System.out.println(name) outputs Sam without being affected by the method's concat function, while System.out.println(names) outputs Sam4 as a result of the method's append method. Why is StringBuilder affected and not String? Normally, calling methods on a reference to an object affects the caller, so I do not understand why the String result remains unchanged. Thanks in advance
public static String speak(String name) {
name = name.concat("4");
return name;
}
public static StringBuilder test(StringBuilder names) {
names = names.append("4");
return names;
}
public static void main(String[] args) {
String name = "Sam";
speak(name);
System.out.println(name); //Sam
StringBuilder names = new StringBuilder("Sam");
test(names);
System.out.println(names); //Sam4
}
Because when you call speak(name);, inside speak when you do
name = name.concat("4");
it creates a new object because Strings are immutable. When you change the original string it creates a new object,I agree that you are returning it but you are not catching it.
So essentially what you are doing is :
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
try
String name = "Sam";
name = speak(name);
Of course now I think there is no need to explain why it's working with StringBuilder unless if you don't know that StringBuilder is mutable.
Looking at the Javadoc for String, one will read that
[...] String objects are immutable [...].
This means concat(String) does not change the String itself, but constructs a new String.
StringBuilders, on the other hand, are mutable. By calling append(CharSequence), the object itself is mutated.
Because String is immutable and hence String#concat does not modify the original String instance, it only returns a new String while the original is left unmodified, while StringBuilder is mutable and the change is reflected in the StringBuilder instance passed as parameter.
Okay, what is speak method doing?
First of all,
name.concat("4");
creates new object, which is equal to name, concatenated with "4".
So, the line
name = name.concat(4);
redefines local (for speak method) variable name.
Then you return the reference to this new value with
return name;
So, the original variable, passed within method is not modified, but the method returns modified value.
In the test method you actually modify variable without modifying the reference (the StringBuilder class is mutable, so variable if this type can be modified).
Then we can see another question arising: why StringBuilder.append returns value, where it can seem redundant. The answer to this question lies in the description of "builder" pattern, for which it is the usual way of implementing modification methods. See wikipedia on Builder pattern.
String is immutable in java. As soon as you invoke concat method on name. A new string is created and while you are playing with the old reference in System.out.println(name).If you want to use the modified string you should explicitly return the reference.
While StringBuilder is mutable and it returns the same reference always.
When you invoke speak(name) it computes the new value, but discards it.
If you replace it with
name = speak(name);
the result will be the one you expect.
With the StringBuilder, the object you pass is mutable: so
names.append(names);
changes the state of the current object (it also returns a reference to the same object, which is just a convenience to allow you to write code like names.append(...).append(...) etc.). So in the case of the StringBuilder, the object you are referencing when you call the method has actually changed, hence you see the changes.
In your method speak, the concat method returns a new String, the original object it was called on is unchanged (strings are immutable). As documented:
If the length of the argument string is 0, then this String object is returned. Otherwise, a String object is returned that represents a character sequence that is the concatenation of the character sequence represented by this String object and the character sequence represented by the argument string.
Calling name.concat("4") is the equivalent of name + "4".
In your test method the append method modifies the content of the StringBuilder. As documented:
The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.
In your main method both name and names are still the same object as before the method call, but the content of name is unchanged as strings are immutable, while the content of names has been changed.
If instead you had used the return values of both methods, then you would have the result you were expecting.
First of all, String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. All information in an instance is initialized when the instance is created and the information can not be modified.
Second, in java parameters are sent by values and not by reference.
In your method 'test' you don't need names = names.append("4"), instead names.append("4") will be enough .
If you check java docs for String object, you will see that most of the methods there, including concat, will generate a new String.
So to have on output Sam4 also for the String, you will need in main method to have this name = speak(name).
String
String is immutable ( once created can not be changed )object . The
object created as a String is stored in the Constant String Pool .
Every immutable object in Java is thread safe ,that implies String is
also thread safe . String can not be used by two threads
simultaneously. String once assigned can not be changed.
String demo = " hello " ; // The above object is stored in constant
string pool and its value can not be modified.
demo="Bye" ; //new "Bye" string is created in constant pool and
referenced by the demo variable // "hello" string still
exists in string constant pool and its value is not overrided but we
lost reference to the "hello"string
StringBuilder
StringBuilder is same as the StringBuffer , that is it stores the
object in heap and it can also be modified . The main difference
between the StringBuffer and StringBuilder is that StringBuilder is
also not thread safe. StringBuilder is fast as it is not thread safe
.
For more details check this
Conclusion:
You don't need to re-assign the value again to StringBuilder as it is already a reference
test method should be
public static void test(StringBuilder names) {
names.append("4");
}
but speak should be
String name = "Sam";
name = speak(name);
This is my code:
public void idoKiiras(){
String idostring = new String();
idostring.valueOf(System.currentTimeMillis());
System.out.print(idostring);
ido.setText(idostring);
}
What i get in the string is nothing, it's empty. Any solution?
String.valueOf() is a static method that returns a String value. Use it like so
String idostring = String.valueOf(System.currentTimeMillis());
System.out.print(idostring);
ido.setText(idostring);
Previously, you were using the valueOf method but not doing anything with its return value.
idostring.valueOf(System.currentTimeMillis());
Remember that String objects are immutable. No String method will ever change the String internally, it will always return a new String object.
#Sotirios already answered this, beautifully, but, I just want to give you a little tip to help anyone that has this problem.
Set the idostring to a silly value at the initialisation phase that way you can see whether it is being changed from the various methods.
E.g
String idostring = "THIS_SHOULD_CHANGE";
That way, when you get to setting the text of ido, you won't have a blank label/button/textview.
public class StringTest
{
public static void main(String... args)
{
String str=null;
System.out.println(str);
}
}
why this code display null? when we pass reference variable into println() method it will call toString() method. For String class, toString() method will be call that returns current object. String str=null means no object is existing.
The documentation reports System.out.println(String):
Prints a String and then terminate the line. This method behaves as though it invokes print(String) and then println().
and the documentation for print(String) reports:
Prints a string. If the argument is null then the string "null" is printed. Otherwise, the string's characters are converted into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.
Your answer is here:
Print a string. If the argument is null then the string "null" is
printed.
Note that "This method behaves as though it invokes print(String) and then println()"
Try
String str="";
null means theres nothing in that memory space... if you use "" that blank space inside will count, will make a space memory for that variable at same time will show nothing ( i think thats it)
I do not know why I am getting an error at the yy.charAt(i) assignments. It says... Variable Expected... Not value.
static int subtract(int x,int y)
{
String yy=Integer.toBinaryString(y);
System.out.println(yy);
for(int i=0;i<yy.length();i++)
{
if(yy.charAt(i)==1)
{
yy.charAt(i)=0;
}
else
{
yy.charAt(i)
}
}
int t=Integer.parseInt(yy);
return(t);
}
You can't assign values to a string's index position, strings are immutable in Java. This will never work:
yy.charAt(i)=0;
If you need to modify a string, transform it to a char[] (using the toCharArray() method), modify the array and then build a new string from that array, using the String(char[]) constructor.
Alternatively, you could use a StringBuilder to modify the characters before returning a new string.
Use a StringBuilder instead.
The code would be almost identical to what you have now, except for these changes:
StringBuilder yy = new StringBuilder(Integer.toBinaryString(y));
...
yy.setChatAt(i, '0');
I think there are a few things that are not clear to you.
I think you mean the character '0' not the value 0.
The lines else { yy.charAt(i); } have absolutely no effect. You can simply omit them.
Strings are immutable in Java (i.e. they cannot be modified in place).
Even if they were, you're syntax is wrong. Something of the form class_name.method_name() is a call to a method of a class. It returns a value that you can store, it is not the same as a variable and trying to assign to a method call makes no sense at all.
To modify Strings in Java, the best way is probably to use a StringBuilder. You create a new StringBuilder using your String, make the necessary changes on that and then convert it back into a String.
So this would look something like this:
StringBuilder builder = new StringBuilder(yy); // StringBuilder from yy.
// rest of your code here
builder.setCharAt(i, '0');
// more code
yy = StringBuilder.toString(); // convert it back to a String.
Notice that even in a StringBuilder you have to call the appropriate method and pass in the value that you want to assign to it.
I want to ask you about the print vector array , the following one:
Vector[] routingTable = new Vector[connectivity.length];
I tried this method , but it doesn't work with me and it gives me protocol.Route#c17164
when I printed in the main, here is the code, so can you tell me why it doesn't print the correct value ?
public String printRT(int hop)
{
String s = "";
for (int i = 0; i < conf.routingTable[hop].size(); i++)
{
s= " ROUTING TABLE " + conf.routingTable[hop].get(i);
}
return s;
}
it looks like you need to implement the toString() method in protocol.Route.
class Route {
public String toString() {
return "some string that makes sense";
}
}
Either override the toString() method on the protocol.Route class, or get the desired properties from the Route object and append them to the String s inside your printRT method.
Many helpful suggestions, but I think everyone is overlooking something very simple- in each loop iteration you are overwriting the value of s. I think you mean to say something like the following instead:
s += " ROUTING TABLE " + conf.routingTable[hop].get(i);
Note the "+=" rather than simple assignment. Or use a StringBuilder, or whatever.
When you ask java to print an object for which no toString method is defined, then it will fall back on the default toString implementation in the Object class. From the javadocs:
The toString method for class Object
returns a string consisting of the
name of the class of which the object
is an instance, the at-sign character
`#', and the unsigned hexadecimal
representation of the hash code of the
object. In other words, this method
returns a string equal to the value
of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
In your example 'protocol.Route' would be the class name and 'c17164' is whatever the hashcode method returns as a hexString, which, unless hashCode has been overwritten, is probably the address of the object, although this is implementation dependent.
So, there are a few ways to fix your problem.
Write your own implementation of the toString method for the Route class that prints out the data you want. This is probably the most "correct" way to fix your problem. It keeps things nicely encapsulated within the class, meaning only the toString method inside of the class needs to know about the exact member variables that are to be printed.
If the situation is such that you cannot change the Route class, you could subclass your own version of the Route class that you could add a toString method to. However, depending on the design of the class, this may be difficult.
Have the current printRT method look inside each Route object and get the specific information that you want to append to the current string.
Also, note that with the current code, you have written the following in the inner loop:
s= " ROUTING TABLE " + conf.routingTable[hop].get(i);
This means that printRT will only return a string for the very last iteration of the loop. So most of the time in the for loop is spent creating strings, assigning them to a variable and then overwriting them the next time through the loop.
If you want to return a string representation for every iteration, you will need to change the above to something like the following:
s += " ROUTING TABLE " + conf.routingTable[hop].get(i);
Now the new information is being appended to s every time through the loop. However, depending on the number of string concatenations being performed, the StringBuilder class may be a better alternative (see a short summary and tutorial on it here).
Two options.
Either override the toString() method on the protocol.Route class.
public String toString() {
return someMethodorPropertyThatreturnsString;
}
or get the desired properties/methods from the Route object and append them to the String s inside your printRT method.
public String printRT(int hop)
{
String s = "";
for (int i = 0; i < conf.routingTable[hop].size(); i++)
{
s= " ROUTING TABLE " + conf.routingTable[hop].get(i).someMethodorPropertyThatreturnsString;
}
return s;
}
There are a number of issues here.
You should be specifying a type to put in your List with Generics. That way, you will make it more obvious to yourself and others what you are putting into and taking out of your List.
As mentioned by others, your List is a list of protocol.Route objects, not Strings. When you try to add a Route to s, Java doesn't know how to convert it into a String, so it uses the default Object#toString(). Override it in Route to do what you want.
It looks like you'll potentially be doing a lot of appending here. Use a StringBuilder.
It looks to me like printRT(int) should be a method inside of whatever conf is.
You should probably be using a different implementation of List; Vector is not really recommended to use anymore, so take a look at other options like ArrayList.