String concat doesnt work [duplicate] - java

I'm trying to replace a character at a specific index in a string.
What I'm doing is:
String myName = "domanokz";
myName.charAt(4) = 'x';
This gives an error. Is there any method to do this?

String are immutable in Java. You can't change them.
You need to create a new string with the character replaced.
String myName = "domanokz";
String newName = myName.substring(0,4)+'x'+myName.substring(5);
Or you can use a StringBuilder:
StringBuilder myName = new StringBuilder("domanokz");
myName.setCharAt(4, 'x');
System.out.println(myName);

Turn the String into a char[], replace the letter by index, then convert the array back into a String.
String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);

String is an immutable class in java. Any method which seems to modify it always returns a new string object with modification.
If you want to manipulate a string, consider StringBuilder or StringBuffer in case you require thread safety.

I agree with Petar Ivanov but it is best if we implement in following way:
public String replace(String str, int index, char replace){
if(str==null){
return str;
}else if(index<0 || index>=str.length()){
return str;
}
char[] chars = str.toCharArray();
chars[index] = replace;
return String.valueOf(chars);
}

As previously answered here, String instances are immutable. StringBuffer and StringBuilder are mutable and suitable for such a purpose whether you need to be thread safe or not.
There is however a way to modify a String but I would never recommend it because it is unsafe, unreliable and it can can be considered as cheating : you can use reflection to modify the inner char array the String object contains. Reflection allows you to access fields and methods that are normally hidden in the current scope (private methods or fields from another class...).
public static void main(String[] args) {
String text = "This is a test";
try {
//String.value is the array of char (char[])
//that contains the text of the String
Field valueField = String.class.getDeclaredField("value");
//String.value is a private variable so it must be set as accessible
//to read and/or to modify its value
valueField.setAccessible(true);
//now we get the array the String instance is actually using
char[] value = (char[])valueField.get(text);
//The 13rd character is the "s" of the word "Test"
value[12]='x';
//We display the string which should be "This is a text"
System.out.println(text);
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

You can overwrite a string, as follows:
String myName = "halftime";
myName = myName.substring(0,4)+'x'+myName.substring(5);
Note that the string myName occurs on both lines, and on both sides of the second line.
Therefore, even though strings may technically be immutable, in practice, you can treat them as editable by overwriting them.

First thing I should have noticed is that charAt is a method and assigning value to it using equal sign won't do anything. If a string is immutable, charAt method, to make change to the string object must receive an argument containing the new character. Unfortunately, string is immutable. To modify the string, I needed to use StringBuilder as suggested by Mr. Petar Ivanov.

You can overwrite on same string like this
String myName = "domanokz";
myName = myName.substring(0, index) + replacement + myName.substring(index+1);
where index = the index of char to replacement.
index+1 to add rest of your string

this will work
String myName="domanokz";
String p=myName.replace(myName.charAt(4),'x');
System.out.println(p);
Output : domaxokz

Related

How to replace specific characters in a string depending on a users guess [duplicate]

I'm trying to replace a character at a specific index in a string.
What I'm doing is:
String myName = "domanokz";
myName.charAt(4) = 'x';
This gives an error. Is there any method to do this?
String are immutable in Java. You can't change them.
You need to create a new string with the character replaced.
String myName = "domanokz";
String newName = myName.substring(0,4)+'x'+myName.substring(5);
Or you can use a StringBuilder:
StringBuilder myName = new StringBuilder("domanokz");
myName.setCharAt(4, 'x');
System.out.println(myName);
Turn the String into a char[], replace the letter by index, then convert the array back into a String.
String myName = "domanokz";
char[] myNameChars = myName.toCharArray();
myNameChars[4] = 'x';
myName = String.valueOf(myNameChars);
String is an immutable class in java. Any method which seems to modify it always returns a new string object with modification.
If you want to manipulate a string, consider StringBuilder or StringBuffer in case you require thread safety.
I agree with Petar Ivanov but it is best if we implement in following way:
public String replace(String str, int index, char replace){
if(str==null){
return str;
}else if(index<0 || index>=str.length()){
return str;
}
char[] chars = str.toCharArray();
chars[index] = replace;
return String.valueOf(chars);
}
As previously answered here, String instances are immutable. StringBuffer and StringBuilder are mutable and suitable for such a purpose whether you need to be thread safe or not.
There is however a way to modify a String but I would never recommend it because it is unsafe, unreliable and it can can be considered as cheating : you can use reflection to modify the inner char array the String object contains. Reflection allows you to access fields and methods that are normally hidden in the current scope (private methods or fields from another class...).
public static void main(String[] args) {
String text = "This is a test";
try {
//String.value is the array of char (char[])
//that contains the text of the String
Field valueField = String.class.getDeclaredField("value");
//String.value is a private variable so it must be set as accessible
//to read and/or to modify its value
valueField.setAccessible(true);
//now we get the array the String instance is actually using
char[] value = (char[])valueField.get(text);
//The 13rd character is the "s" of the word "Test"
value[12]='x';
//We display the string which should be "This is a text"
System.out.println(text);
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
You can overwrite a string, as follows:
String myName = "halftime";
myName = myName.substring(0,4)+'x'+myName.substring(5);
Note that the string myName occurs on both lines, and on both sides of the second line.
Therefore, even though strings may technically be immutable, in practice, you can treat them as editable by overwriting them.
First thing I should have noticed is that charAt is a method and assigning value to it using equal sign won't do anything. If a string is immutable, charAt method, to make change to the string object must receive an argument containing the new character. Unfortunately, string is immutable. To modify the string, I needed to use StringBuilder as suggested by Mr. Petar Ivanov.
You can overwrite on same string like this
String myName = "domanokz";
myName = myName.substring(0, index) + replacement + myName.substring(index+1);
where index = the index of char to replacement.
index+1 to add rest of your string
this will work
String myName="domanokz";
String p=myName.replace(myName.charAt(4),'x');
System.out.println(p);
Output : domaxokz

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();

Incompatible Types: Returning a new String object

I've been working on a little project writing my own custom String methods. (replace,concat, etc...) to manipulate strings in an object oriented design.
In my class definition (MyString) I wrote a concat() method that has a return type of a MyString.
public MyString concat(MyString sent)
{
char[] newString = new char[sequence.length + sent.sequence.length];
for(int i = 0; i< sequence.length;i++)
{
newString[i] = sequence[i];
}
for(int i = sequence.length; i < newString.length; i++)
{
newString[i] = sent.charAt(i - sequence.length);
}
sent.sequence = newString;
return sent;
In my driver A user will enter a string. and then be prompted to enter another string to be concatenated. when I go to call the method I'm getting an incompatible types error saying the String I'm sending into it (compString) can't be converted to a new MyString. I created a new MyString object, and sent in the new String, which I thought was the right thing to do...
MyString ms = new MyString(compString);
System.out.println("Calling the concat() method: " + ms.concat(compString) );
I want to concatenate compString onto the original string, both of with are MyStrings. How would I go about calling this method? "ms" being the reference variable to the original string. Do I need a new MyString object in order to accomplish this?
public MyString(String sent)
{
origional = new String(sent);
sequence = origional.toCharArray();
}
Here is my constructor just in case.
You're passing a String into your concat() method, which expect MyString. Try wrapping it in your class first:
ms.concat(new MyString(compString))
I have to admit, this still doesn't make much sense. ms is already a wrapper for compString. Are you trying to concat a string to itself? Then just do ms.concat(ms).
You need to override the toString function so that the println() function will properly print out your custom string.
You also need to match the expected MyString type parameter for your concat(MyString sent) function.
Something like:
class MyString {
public String toString()
{
return sequence;
}
}
MyString ms = new MyString(compString);
// making assumption that compString is a standard string
System.out.println("Calling the concat() method: " + ms.concat(new MyString(compString)) );

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.

How do String objects work (like immutable objects)?

I have these two situations:
String s = "aa";
s = s + " aa";
System.out.println(s);
//......
that work fine! It prints aa aa.
But there is a problem:
String s = "aa";
this.addStringToStatement(s, " aa");
System.out.println(s);
//...
private void addStringToStatement(String statement, Object value) {
statement += value;
}
It prints: aa.
What is the reason??
Thanks!
There are two issues to understand here.
The String append operator will create a new immutable String object. The expression s + value is a different object in memory from s.
In your function addStringToStatement when you execute statement += value; you aren't changing the value of the variable s, rather you are reassigning the local pointer statement to a new String instance.
EDIT: Fixed usual noob mistake: In Java, object references are passed, not the objects themselves.
This is because in Java a reference is passed by value. Here when you passed s and " aa" as two parameters.
In the method statement variable (which has reference of s) is altered to point to something else ie "aa aa". Note only the statement reference is passed, s is still pointing to "aa".
So when you print s you get what is expected :)
this is because of how passing by value works in Java, you need to do something like this:
String s = "aa";
s = this.addStringToStatement(s, " aa");
System.out.println(s);
//...
private string addStringToStatement(String statement, Object value) {
statement += value;
return statement;
}
Strings in Java are immutable. If you have a String s="aa", you only have a reference to the String "aa" inside the JVM. If you want the String "aa aa" assigned to s, you assign only the reference (address) to "aa aa" (another String inside the JVM) to s, "aa" lurks still somewhere in the JVM.
The statement "Java references are passed by value" is somewhat confusing (if true). If you use a StringBuilder sb and give this StringBuilder to a function, the reference is "copied" but still points to the same object as sb:
public static void main(String[] args) {
final StringBuilder sb = new StringBuilder();
f(sb);
System.out.println(sb);
}
private static void f(final StringBuilder sb) {
sb.append("aa aa");
}
You have to return the "statement" variable. Without the "this.*" part.
String s = "aa";
s = addStringToStatement(s, " aa");
System.out.println(s);
//...
private String addStringToStatement(String statement, Object value) {
statement += value;
return statement;
}
#Frank Meißner (new to this, can't reply to answers yet)
Just to clarify the difference between String and StringBuilder (in case anyone reading this is confused), while both store the CharSequence they hold as a char[], the char[] within String cannot be changed, thus a new String has to be created for every alteration. In the case of a StringBuilder, there are methods like StringBuilder.append(String) that can change the internal char[] of the StringBuilder, so if StringBuilder.append(String) is called, no new object will have to be created for the content of the StringBuilder to change.
As per Frank Meißner's example, System.out.println(sb); will print "aa aa", since the method append(String) was called on the StringBuilder sb. final doesn't hurt here since the identity of sb isn't changed, only its state.
+= in case of string doesn't modify string itself but produce new string. in case of your method you set this new string reference to local variable (parameter)
Java references are passed by value. When you pass a String to a method and it changes inside it points to different String. You can either return the String after appending or use StringBuffer as argument.

Categories