- A string is a ==sequence of characters==.
- Strings are one of the most commonly used data types in Java and are represented by the ==String class in the java.lang package.==
- A string in Java is ==immutable==, meaning once it is created, its content cannot be changed.

Consider the below code!
String a = "JD";
String b = "JD";Both a,b are stored in stack and the String Objects are stored in heap! does above code ==makes a,b point to same obj or diff identical objects??==
-
A seperate memory or structure inside heap.
-
Speciality : similar string objs are not created! ==UNIQUE OBJ ONLY==
-
So from the above ex inside note, both a,b points to same single instance of OBJ "JD" inside string pool.
-
==Makes code optimal.==
-
Srings are immutable due to some security reasons.
String a = "JD"; System.out.println(a); a = "iamjayandhan"; System.out.println(a);
This results:
JD iamjayandhan
-
Here reference variable is made to point newly created obj "iamjayandhan". Now the object "JD" has no ref var pointing! This obj "JD" now will be garbage collected.
-
==IF WE MODIFY, WE ACTUALLY CREATE NEW STRING OBJ EVERYTIME!==
-
first it will check pool, if it is already there then it will reuse. Else it will create a new obj.
ex : consider 5 persons a,b,c,d,e has same name "JD"
a,b,c,d,e -> "JD"
if one person changes his same, all others name will also gets changed! so for this reason, java security concerns over strings and behaves like this.
now one person "a" changes his name to "jimmy", now: a -> "jimmy" b,c,d,e -> "JD"
Thus SECURE😇
String c = new String("JD");
String d = new String("JD");This way, obj are created outside the string pool. Thus duplicates are allowed! They will be inside heap, outside pool.
- == method (Comparator):
- Checks if ref vars are pointing to same obj.
- .equals():
- checks only the values, not ref.
src: Java Memory Management and Garbage Collection in Depth goto : MM&GC folder
Everytime we use println(), the following process occurs to print that int value in console as string.
System.out.println(48);java.base\java.io\PrintStream.class
/**
* Prints an integer and then terminate the line. This method behaves as
* though it invokes {@link #print(int)} and then
* {@link #println()}.
*
* @param x The {@code int} to be printed.
*/
public void println(int x) {
synchronized (this) {
print(x);
newLine();
}
}java.base\java.io\PrintStream.class
/**
* Prints an integer. The string produced by {@link
* java.lang.String#valueOf(int)} is translated into bytes
* according to the platform's default character encoding, and these bytes
* are written in exactly the manner of the
* {@link #write(int)} method.
*
* @param i The {@code int} to be printed
* @see java.lang.Integer#toString(int)
*/
public void print(int i) {
write(String.valueOf(i));
}java.base\java.lang\String.class
/**
* Returns the string representation of the {@code int} argument.
* <p>
* The representation is exactly the one returned by the
* {@code Integer.toString} method of one argument.
*
* @param i an {@code int}.
* @return a string representation of the {@code int} argument.
* @see java.lang.Integer#toString(int, int)
*/
public static String valueOf(int i) {
return Integer.toString(i);
}java.base\java.lang\Integer.class
/**
* Returns a {@code String} object representing the
* specified integer. The argument is converted to signed decimal
* representation and returned as a string, exactly as if the
* argument and radix 10 were given as arguments to the {@link
* #toString(int, int)} method.
*
* @param i an integer to be converted.
* @return a string representation of the argument in base 10.
*/
@HotSpotIntrinsicCandidate
public static String toString(int i) {
int size = stringSize(i);
if (COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
StringUTF16.getChars(i, size, buf);
return new String(buf, UTF16);
}
}==Conversion Flow:== println(int) → print(int) → String.valueOf(int) → Integer.toString(int).
System.out.println(new int[]{1,2,3,4,5});java.base\java.io\PrintStream.class
/**
* 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 {@link #print(String)} and then
* {@link #println()}.
*
* @param x The {@code Object} to be printed.
*/
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}java.base\java.io\PrintStream.class
/**
* Prints a string. If the argument is {@code null} then the string
* {@code "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
* {@link #write(int)} method.
*
* @param s The {@code String} to be printed
*/
public void print(String s) {
write(String.valueOf(s));
}java.base\java.lang\String.class
/**
* Returns the string representation of the {@code Object} argument.
*
* @param obj an {@code Object}.
* @return if the argument is {@code null}, then a string equal to
* {@code "null"}; otherwise, the value of
* {@code obj.toString()} is returned.
* @see java.lang.Object#toString()
*/
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}java.base\java.lang\Object.class
/**
* Returns a string representation of the object. In general, the
* {@code 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.
* <p>
* The {@code toString} method for class {@code Object}
* returns a string consisting of the name of the class of which the
* object is an instance, the at-sign character `{@code @}', 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:
* <blockquote>
* <pre>
* getClass().getName() + '@' + Integer.toHexString(hashCode())
* </pre></blockquote>
*
* @return a string representation of the object.
*/
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
} [I@2401f4c3
//here '[' - represents 1D array
// 'I' - Integer Array
// '@' - seperator
// '2401f4c3' - computed hash code for obj==Conversion Flow:== println(Object) → String.valueOf(Object) → obj.toString() → Object.toString().
Override default Object's toString()? Yes with the help of Arrays class
import java.util.Arrays;
System.out.println(Arrays.toString(new int[]{1,2,3,4,5})); //uses StringBuilder!Implementation
/**
* Returns a string representation of the contents of the specified array.
* The string representation consists of a list of the array's elements,
* enclosed in square brackets ({@code "[]"}). Adjacent elements are
* separated by the characters {@code ", "} (a comma followed by a
* space). Elements are converted to strings as by
* {@code String.valueOf(int)}. Returns {@code "null"} if {@code a} is
* {@code null}.
*
* @param a the array whose string representation to return
* @return a string representation of {@code a}
* @since 1.5
*/
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
} //Result
[1,2,3,4,5]so both are also objects right? then why hashval is not printed in that case? TRUTH: Default 'toString()' of Object is overridden by 'toString()' method present in String class and Integer class! Look below example:
//Strings are objects
System.out.println("JD"); //JD , not hashval!toString gets overridden by this:
/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
} //Wrappers are Objects
Integer a = 48;
System.out.println(a); //48, not that hashval!toString default obj function is overridden by this:
public String toString() {
return Integer.toString(value);
}- Primitives are stored in stack memory.
- Objects are stored in heap.
Plus (+)
- can only be used with primitives, or if anyone is them is string.
- obj+obj wont work, but obj+""+obj works => makes it a complete string.
- operator overloading is not supported in java(results in poor code.)
- ==Only operator that is overloading is + in java. To support string concatenation.==
String series = "";
//code creates 25 obj and 26th obj is returned, others are garbage collected.
//not efficient code as strings are immutable
//memory wastage occurs. so many dereferences.
//1+2+3.....N
//N(N+1)/2 => O(N^2) complexity!
for(int i=0;i<26;i++){
series += (char)('a'+i);
}
System.out.println(series);==What if there is a way to modify strings? any wrapper?==
Only one object is made and changes are applied in that obj only.
StringBuilder series2 = new StringBuilder(); //Obj
for(int i=0;i<26;i++){
series2.append((char)('a'+i)); //changes are made on one obj only. New are not created everytime!
}
System.out.println(series2);