Difference between new String(char[]) and char[].toString - java

The output for following two code blocks in Java is different. I am trying to understand why.
private String sortChars(String s){
char[] arr = s.toCharArray(); //creating new char[]
Arrays.sort(arr); //sorting that array
return new String(arr);
}
This one returns a string with sorted characters as expected.
private String sortChars(String s){
char[] arr = s.toCharArray(); //creating new char[]
Arrays.sort(arr); //sorting that array
return arr.toString();
}
Sorry. My bad!
Using to compare two strings.
The output to second string looks like this as suggested by many -
[C#2e0ece65
Thanks!

In Java, toString on an array prints [, then a character representing the array element type (C in this case) and then the identity hash code. So in your case, are you sure it is returning the original string and not something like [C#f4e6d?
Either way, you should use new String(arr). This is the shortest, neatest, way of converting a char[] back to a String. You could also use Arrays.toString(arr)
Related trivia
The reason that your arr.toString() method returns something like [Cf4e6d is that Object.toString returns
getClass().getName() + '#' + Integer.toHexString(hashCode())
For a char array, getName() returns the string [C. For your program you can see this with the code:
System.out.println(arr.getClass().getName());
The second part of the result, Object.hashCode(), returns a number based on the object's memory address, not the array contents. This is because by default the definition of "equals" for an object is reference equality, i.e. two objects are the same only if they are the same referenced object in memory. You will therefore get different arr.toString() values for two arrays based on the same string:
String s = "fdsa";
char[] arr = s.toCharArray();
char[] arr2 = s.toCharArray();
System.out.println(arr.toString());
System.out.println(arr2.toString());
gives:
[C#4b7c8f7f
[C#5eb10190
Note that this is different for the String class where the equality rules are overridden to make it have value equality. However, you should always use string1.equals(string2) to test for string equality, and not == as the == method will still test for memory location.

Related

Why we can't add character at certain position by charAt(index) in java

public class ReverseString {
public static void main(String[] args) {
String s = "mnop";
s.charAt(0) = 'l';
}
}
Java only allows you to assign to variables, fields and array elements.
The result of a method - like s.charAt(0) - is none of these, so you can't assign to it.
The reason for this is down to the way Java returns: it returns by value, not by reference, and that value only exists temporarily. As such, if you were able to assign it, the side effect of that assignment is immediately lost, making it pointless.
It's also true that String is immutable; but this limitation on what you can assign to is the reason you couldn't do this even for some notional MutableString class you might try to create.
Strings in java are immutable, meaning they can't change at all.
To do something like this, use a StringBuilder:
StringBuilder sb = new StringBuilder("mnop");
sb.setCharAt(0, 'l');
//later, you probably want to get back to a String:
String s = sb.toString();
s.charAt(0) returns a char value, not a char variable to which you could assign a value.
And anyway, String is immutable, so you can't modify the value of an existing String.
You can obtain a copy of the array of all the characters of the String, and modify that array:
String s = "mnop";
char[] chars = s.toCharArray();
chars[0]= 'l';
However, this doesn't modify the original String, since it's immutable.
You can create a new String using that array though:
String newS = new String(chars);
charAt returns a char that's a copy of the character at that position in the string. It's not a reference back to the original string, which is immutable.
You could use a StringBuilder instead, though:
StringBuilder sb = new StringBuilder("mnop");
sb.setCharAt(0, 'l');
String s = sb.toString();

Why does String not work as "pass by reference" in spite of being an array of characters

I understand that on passing an array asn argument to a function, and making some change to the elements of the array inside the function, the changes will be reflected in the calling function as well, since arrays operates directly on memory (call by reference)
However, why is it that the same behavior does not apply to Strings? I was expecting Strings as well to work in the same way since a String is basically an array of characters.
Please see my code below.
I pass in a String (character array) as well as an int array in to a function and make some changes in it. On printing these in main, I see that the String remains unaffected whereas the changes to the array are reflected.
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static void fun(String s, int[] a)
{
s = "world";
a[0] = 99;
}
}
Output
hello
99
First, the claim that a String is an array of characters is wrong. A String is an object, that has methods and is designed specifically not to allow any changes to be made in it.
Second, what you are doing is not changing some element of the parameter. You are changing the parameter variable. The parameter variable is basically a local variable, which receives a reference to the string that was passed as argument. Doing this:
s = "world";
Is not changing the string that was passed. It replaces contents of the local variable s with a new string. Since Java is always pass by value, this is not reflected outside of the method. It would be the same if you had:
a = new int[30];
inside the method. Outside of it you would still see the 5-element int[] that you passed inside.
a[0] = 99;
Is changing an element inside the array. So it looks at a, checks what it refers to, goes to that referred array, and changes its 0th element.
Since String is designed to be immutable, there is no way to do something similar in it. You can't do something like:
s.setCharacter(0,'a'); // This doesn't exist in Java
But you can do this with mutable objects. For example, if you had:
public static void manipulateStringBuilder( StringBuilder sb ) {
sb.append(": manipulated");
sb = new StringBuilder("New value assigned");
}
Then you could write something like:
StringBuilder sb = new StringBuilder("My string");
System.out.println(sb);
manipulateStringBuilder( sb );
System.out.println(sb);
And the output would be:
My string
My string: manipulated
This is because StringBuilder is a mutable object, combined with the fact that the value that you assigned to sb inside your method is never seen outside of it.
Because Strings in java are immutable. Every "change" done to a string does not changes the original string but creates a new String object.
It is because Strings are immutable. If you want to change the value of the String you should return it from the method and store it in the variable s again.
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
s = fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static String fun(String s, int[] a)
{
s = "world";
a[0] = 99;
return s;
}
}
I expect it will be helpful for you!
Java is not call by reference, but call by value, it is just that it passes references as values. More details here.
Strings are immutable, so you can't change the content (the char array) of a String, you can just replace it with a different one, i.e. you are changing the reference. But since the reference is passed by value, the change is not visible outside a method.
Actually you can change the content of String using reflection, which results in very interesting behavior. You use this only when you want to play a prank on a coworker.

Printing String Array [duplicate]

This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
Closed 8 years ago.
Here is my code:
String[] magic = {"stick", "hat", "witch"};
String magic1 = magic.toString();
String magic2 = Arrays.toString(magic);
System.out.println(magic1); // this is printing a memory location
System.out.println(magic2); // this one prints: [stick, hat, witch]
What is the difference between magic1 and magic2?
Arrays are objects, but they don't change (override) its toString() method, which means they use default one, inherited from Object. If you read documentation of this method you will find:
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 case
getClass().getName() returns [Ljava.lang.String which means
one dimensional array (because there is only one [)
of type which full name is java.lang.String
and Integer.toHexString(hashCode()) returns something like 1db9742 which is hexadecimal form of integer returned by hashCode() method.
Now if you take a look at code of Arrays.toString(Object[] array) (String[] is considered as Object[])
4531 public static String toString(Object[] a) {4532 if (a == null)4533 return "null";4535 int iMax = a.length - 1;4536 if (iMax == -1)4537 return "[]";4539 StringBuilder b = new StringBuilder();4540 b.append('[');4541 for (int i = 0; ; i++) {4542 b.append(String.valueOf(a[i]));4543 if (i == iMax)4544 return b.append(']').toString();4545 b.append(", ");4546 }4547 }
you will see that its purpose is to create string build from content of this array. It does this by iterating over all elements and adding their string representation to StringBuilder which is then used to create String which will be returned.
It is basically a tailored toString which makes the output pretty.
What you see in the first toString is the memory address . Reason being that the variable-name is just that - a memory address( aka reference ).
Every class inherits toString, and can implement its own.
See Arrays class API
String[] names = {"Bob", "Dad", "Mom"};
String names1 = names.toString();
String names2 = Arrays.toString(names);
System.out.println(names1 );
System.out.println(names2 );
prints out:
[Ljava.lang.String;#1034bb5
[Bob, Dad, Mom]
Read the doumentation. I have copied the necessary information here.
public static String toString(Object[] a)
Returns a string representation of the contents of the specified array. If the array contains other arrays as elements, they are converted to strings by the Object.toString() method inherited from Object, which describes their identities rather than their contents.
The value returned by this method is equal to the value that would be returned by Arrays.asList(a).toString(), unless a is null, in which case "null" is returned.
public String toString()
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
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())

toString in the java code

The following is my java code snippet:
static String sortChars(String s) {
char[] chars = s.toCharArray();
Arrays.sort(chars);
return chars.toString();
}
I invoke above function by using:
String result = sortChars(s);
But the result does not meet my expectation:for example,the s="are", the result="aer". However, when I use:
return new String(chars)
It works.
Could somebody tell me the reason of it. Thanks
Since char[] class does not override the default Object's toString() implementation, it does not return a string composed by the characters in the char array, but the char[] class name + hash code. For example: arr[C#19821f.
toString() returns a string representation of the Object. You can look at it as a description of the object.
new String(chars) will give you a String with the content of the char array.
Use toString() if you want to represent an Object to the user or in a log, use new String() if you want to get a String object that is the same as the content of your array
Note that, among the constructors for a Java String is one that accepts a character array. That converts the character array into a string as you would expect, and it is the correct choice for what you are doing.

Removing Backing Array From Strings

I want to get the first 4 characters of a string to compare with another string. However, when I do something like
String shortString;
shortString = longString.subString(0,3);
It takes along longString's backing array and makes it impossible to compare easily.
I've also tried converting longString into a character array and inserting each character but I always seem to end up with long string. The Android Development documents say to use the String constructor to remove the backing array but it doesn't seem to work for me either.
String shortString = new String(longString.subString(0,3));
Any suggestions would be appreciated!
First, it's string.substring() not .subString().
Second, what do you mean "impossible to compare easily"? You can compare strings with .equals() easily.
public static void main(String[] args) {
String longString = "abcdefghijklmn";
String shortString = longString.substring(0, 3);
System.out.println(shortString.equals(longString));
}
this code prints false, as it should.
Update:
If you call .substring() so that it produces string of the same length as original string (e.g. "abc".substring(0,2)) than it will return reference to the same string. So, .equals() in this case will return true.
How would you want to compare? There's built in method for simple comparison:
longString.subString(0, 3).compareTo(anotherString);
Alternatively, since String is a CharSequence, something like:
for (int i=0; i<4; i++){
if (anotherString.charAt(i) != shortString.charAt(i)) return false;
}
would work as well.
Finally, every String is constructed in backing Array, there's no way to deny it, and longString.subString(0,3) would always (except index out of bound) return a String with a 4-element Char Array.
In the event that you actually need to get rid of the backing array the following will work:
String newString = StringBuilder(oldString).toString();
This might be necessary, for example, if you are parsing strings and creating substrings and you might need to do this:
String newString = StringBuilder(oldString.substring(start,end).toString();
This creates a truly new string with a zero offset and independent backing array. Otherwise, you maintain the same backing array which, in rare cases might cause a problem for the heap because it can never be garbage collected.

Categories