I have some question that I wonder about. I know that string are immutable in Java and therefore a new string object is created rather than changed when for example assigning to a existing string object.
Now to my question. Let's suppose that I have the following piece of code:
String a = "Hello World";
String b = "Hello World";
String res = a.substring(0,4) + b.substring(6,10);
How many string objects will be created by the code at line 3 ? Will each call to substring create a new string object ? Will my code above generate 3 new string objects ?
Thanks in advance
Strings in Java are immutable. Basically this means that, once you create a string object, you won't be able to modify/change the content of a string. As a result, if you perform any manipulation on a string object which "appears to" change the content of the string, Java creates a new string object, and performs the manipulation on the newly created one.
Based on this, your code above appears to create five string objects - two are created by the declaration, two are created by calls to substring, and the last one is created after you concatenate the two pieces.
Immutability however leads to another interesting consequence. JVM internally maintains something like a string pool for creating string literals. For saving up memory, JVM will try to use string objects from this pool. Whenever you create a new string literal, JVM will loop into the pool to see if any existing strings can be used. If there is, JVM will simply use it and return it.
So, technically, before Java 7, JVM will create only one string object for your whole code. Even your substring calls won't create new string objects in the pool, it will use the existing "Hello World" one, but in this case it will only use characters from position 0 to 3 for your first call to substring, for example. Starting from Java 7, substring will not share the characters, but will create a new one. So, total object count will be 4 - the last one will be created with the concatenation of the two substrings.
Edit
To answer your question in the comment, take a look at Java Language Specification -
In the Java programming language, unlike C, an array of char is not a
String, and neither a String nor an array of char is terminated by
'\u0000' (the NUL character).
A String object is immutable, that is, its contents never change,
while an array of char has mutable elements.
The method toCharArray in class String returns an array of characters
containing the same character sequence as a String. The class
StringBuffer implements useful methods on mutable arrays of
characters.
So, no, char arrays are not immutable in Java, they are mutable.
Literal a is created newly and kept in the pool.Literal b refer the a, it will not create new one instead.
The line 3 will create 3 new String since substring creates a new string and concatenate creates new Strings every time.
String substring(int beginIndex,int endIndex)
Returns a new string that is a substring of this string. The substring
begins at the specified beginIndex and extends to the character at
index endIndex - 1. Thus the length of the substring is
endIndex-beginIndex.
Related
This question already has answers here:
String can't change. But int, char can change
(7 answers)
Closed 9 years ago.
String s1 = "ABC";
s1.replace("ABC","abc");
print(s1); // prints ABC as output
s1 = s1.replace("ABC","abc");
print(s1); //prints abc
What's the difference between two replace statements?
What happens internally when the first replace statement is called?
String.replace(CharSequence first, CharSequence second) returns a new String reference and this is why the output is different.
In the first replace line you're not assigning the resulting String to anything, whereas in the second you're replacing the reference of s1 with the result of the replacement.
s1.replace("ABC","abc"); doesn't replace on s1. It gives output of the replaced string.
$s2 = s1.replace("ABC","abc");;
print($s1); // prints ABC
print ($s2); // prints abc
Strings are immutable. It means changes are not made directly into them instead a copy of the string is created and it is changed and the reference of the changed one is returned. If you do not accept the new reference you will find the old string unchanged.
Read the API and the Java tutorials... String can NEVER be changed. That means all its methods will return a new object and your reference will still point to the old one. To assign the return to your reference, you have to assign it as in
s1 = s1.replace("ABC","abc");
Be careful with that! Quite tricky ;)
If you will change the String a lot, use StringBuffer instead... There your appends, replaces, etc have effect in the object referenced by your variable.
String.replace() Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
Code of String.replace
When you do s1.replace("ABC", "abc") imagine that in that place new string abc is created and not assigned to anything. But with s1=s1.replace("ABC", "abc") you create new string abc and assign it to the s1 variable replacing old value.
I want to know, if a String is a collection. I have read around but am still quite confused.
Strings are immutable objects representing a character sequence (CharSequence is one of the interfaces implemented by String).
Main difference to char arrays and collections of chars: String cannot be modified, it's not possible (ignoring reflection) to add/remove/replace characters.
Internally they are represented by a char array with an offset and length (this allows to create lightweight substrings, using the same char arrays).
Example: ['F','o','o','H','e','l','l','o',' ','W','o','r','l','d'], offset=3, count=5 = "Hello".
strings are object of class String and it's not a Collection as well. It is implemented on top of char array. You can see it in the below code snippet:
public final class String implements
java.io.Serializable, Comparable<String>, CharSequence
{
private final char value[];
No, it's not a collection in that it does not implement the Collection<E> interface.
Conceptually, it is an immutable sequence of characters (and implements the CharSequence interface).
Internally, the String class is likely to use an array of chars, although I am pretty sure the spec does not mandate that.
No, A string is an object of class String
The String class represents character strings. All string literals in
Java programs, such as "abc", are implemented as instances of this
class....
A String represents a string in the UTF-16 format in which
supplementary characters are represented by surrogate pairs (see the
section Unicode Character Representations in the Character class for
more information). Index values refer to char code units, so a
supplementary character uses two positions in a String.
No it's not an Array or a Collection. However there is a convenient method if you need a char array and you have a String - namely String.toCharArray(); you could use it like this
// Prints the String "Hello, World!" as a char[].
System.out.println(Arrays.toString("Hello, World!".toCharArray()));
No, a String is an immutable string of characters, and the class extends Object directly and does not implement any of the Collection interfaces. Really, that's the basic answer.
However, there's a lot going on under the covers in the runtime--there's a whole collection of cached strings held by the JVM and in its most primitive representation, yeah, a String is basically an array of characters (meaning it's a bunch of memory addresses pointing to representations of characters). Still, once you go below the definition of String as it's defined as a class, you can keep going until you get to the point that you're just talking about organized combinations of ones and zeroes.
I'm guessing here, but I imagine you posed the question because you're studying this and an instructor said something about a String being an array of characters. While technically correct, that's really confusing because the two concepts exists at completely different levels of abstraction.
String Class is just a class which allows you to create objects of strings. Like all classes it makes easy the use of these objects using its owns methods.
An array of char is an string, but its methods are relative to arrays or the elements of the array.
So for example if you want to look for the position of a carácter in an string of a class String then you use a method called IndexOf.
But if you want to find a character in an array of char, then you would have to do it manually using loops.
In C++ I can do something like this...
String s = "abc";
char c = s[i]; // works fine...
But in Java, if I try doing the same, it throws an error. Why?.
In java, to achieve the above, I have to do :
s.toCharArray();
How is the implementation of Strings in C++ different from that in Java?
In java, to achieve the above, I have to do :
s.toCharArray();
Not really. You can use charAt instead:
char c = s.charAt(i);
Basically, C++ allows user-defined operators - Java doesn't. So the String class doesn't expose any sort of "indexing" operator; that only exists for arrays, and a String isn't an array. (It's usually implemented using an array, but that's a different matter.)
EDIT: As noted in comments, the + operator is special-cased for strings - right in the language specification. The same could have been done for [], but it isn't - and as it's not in the language specification, and Java doesn't support overloaded operators, it can't be performed in library code. (For example, you can't give custom behaviour to + for any other class.)
The difference is that C++ has operator overloading, and uses it to access the string contents.
They both store the string characters in such a way as you cannot change them.
The reason that it is possible to write
string s = "abc";
char c = s[i];
in C++ is that the string class has overloaded the indexing operator (say [] operator) which allows programmers to access characters of a string object the same way that they access an element of an array, despite the fact that a string object is not an array.
Java, on the other hand, does not allow operator overloading of any kind (the only exception is the + operator that is overloaded for strings) and hence, the indexing operator is not and can not be overloaded for String objects. In Java, to access a character of a string, you need to use accessor member methods, such as charAt. You can also invoke the toCharArray method of the String class, which returns to you an array of the characters of the string object and you can use the indexing operator with this returned value:
char c = s.toCharArray()[i];
See the method String#charAt
Returns the char value at the specified index. An index ranges from 0 to length() - 1. The first char value of the sequence is at index 0, the next at index 1, and so on, as for array indexing.
If the char value specified by the index is a surrogate, the surrogate value is returned.
public char charAt(int index)
in c++ strings are already treated as array of characters,
but in java String is a built in class.
it is different from array of characters.
In C++, a string is typically just an array of (or a pointer to) chars, terminated with a NULL (\0) character. You can process a string by indexing also as you would process any array.
But in Java , a strings are not arrays. Java strings are objects of type java.lang.String so You cannot process them by indexing .
In my program I'm trying to compare my char array asterixA[] to a String word in an if condition like:
if (word.equals(asterixA))
but it's giving me an error. Is there any other way I can compare them?
you have to convert the character array into String or String to char array and then do the comparision.
if (word.equals(new String(asterixA)))
or
if(Arrays.equals(word.toCharArray(), asterixA))
BTW. if is a conditional statement not a loop
You seem to be taking the "A String is an array of chars" line too literal. String's equals method states that
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
It all depends of the circumstances, but generally you compare two objects of the same type or two objects belonging to the same hierarchy (sharing a common superclass).
In this case a String is not a char[], but Java provides mechanisms to go from one to the other, either by doing a String -> char[] transformation with String#toCharArray() or a char[] -> String transformation by passing the char[] as a parameter to String's constructor.
This way you can compare both objects after either turning your String into a char[] or vice-versa.
You can compare the arrays:
if (Arrays.equals(asterixA, word.toCharArray()) {}
do as follows: if (word.equals(new String(asterixA))) { ... }
OK, this is the line I am working on:
newstring.charAt(w) += p;
trying to add a character/char (p) to the string 'newstring' at a particular position within the string which is defined by int 'w'. Is this possible?
Strings are immutable in Java, so the answer is no. But there are many ways around it. The easiest is to create a StringBuilder and use the setCharAt() method. Or insert() if you want to insert a new character at a given position.
If you make multiple modifications to your string, you can (and indeed should) reuse your StringBuilder.
Well, you can't modify your string, because Strings are immutable in Java. If you try to change the string, you will get a new string object as a result.
Now, you can use String#substring method for that, using which you can get new string which is generated by some concatenation of substring of original string.: -
str = str.substring(0, w) + "p" + str.substring(w);
But, of course, using StringBuilder as specified in #biziclop's answer is the best approach you can follow.