Java String & Var-args

Prepared By SRIKANTH MAMILLAPALLI

Java Training Notes • String, StringBuffer, StringBuilder, Immutability & Var-args

1. String

  • String objects are immutable, whereas StringBuffer objects are mutable.
  • Immutable means unmodifiable or unchangeable.
  • Once a String object is created, changes cannot be performed on the existing object.
  • If a modification is attempted, a new String object is created.
  • Strings are sequences of characters and are treated as objects in Java.
  • The Java platform provides the String class to create and manipulate strings.
Key point: String immutability means the original String object's state does not change when methods such as concat() are called.

2. Creating Strings

The most direct way to create a String is by using a string literal:

String greeting = "Hello world!";
  • Whenever the compiler encounters a string literal, a String object is created with that value.
  • String objects can also be created using the new keyword and a constructor.
  • The source material notes that String provides constructors for initializing strings from different sources, such as character arrays.

Creating from a character array

public class StringDemo {
    public static void main(String[] args) {
        char[] helloArray = { 'h', 'e', 'l', 'l', 'o' };
        String helloString = new String(helloArray);
        System.out.println(helloString);
    }
}
Note: The String class is immutable; once a String object is created, its value cannot be changed.

3. String Length

The length() method returns the number of characters contained in a String.

public class StringDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";
        int len = palindrome.length();
        System.out.println("String Length is : " + len);
    }
}

Output:

String Length is : 17

4. Concatenating Strings

The String class provides concat() to append one String to another.

string1.concat(string2);

For example:

"My name is ".concat("Sree");

Strings are also commonly concatenated using the + operator:

"Hello," + " world" + "!"

Result:

"Hello, world!"

5. Creating Strings with new — equals() and ==

String s1 = new String("SAI");
String s2 = new String("SAI");

System.out.println(s1 == s2);       // false
System.out.println(s1.equals(s2));  // true
ComparisonStringStringBuffer
MutabilityImmutableMutable
equals()Overridden for content comparisonNot overridden for content comparison
==Compares object references
  • String.equals() compares content.
  • == compares references.
  • StringBuffer inherits Object's equals behavior, so its equals comparison is reference-based.

Using the new keyword

class Main {
    public static void main(String[] args) {
        String name = new String("Java String");
        System.out.println(name);
    }
}

6. String Memory: Heap and String Constant Pool

The notes distinguish String objects created using new from String literals.

new String("SAI")

SAI

A new object is created in the heap. The literal may also be represented in the String Constant Pool (SCP).

String s = "SAI"

SAI

The String literal is obtained from the String Constant Pool when the same content is already available.

String Constant Pool rules described in the notes

  • Object creation in the SCP is optional.
  • Java first checks whether an object with the required content is already present in the SCP.
  • If present, the existing pooled object can be reused.
  • If not present, a new pooled object is created.
  • This reuse rule applies to the SCP, not to heap objects created with new.
  • Heap objects without references can become eligible for garbage collection.
Memory areas listed in the notes: Heap, Stack, Method Area, PC-Register and Native Method Stack.

The source notes state that SCP objects are associated with JVM lifetime and are destroyed when the JVM shuts down/restarts.

7. Runtime String Objects and Concatenation

The notes explain that runtime-created String objects are placed in the heap and can become eligible for garbage collection when no reference remains.

public void stringDemostration() {
    String s1 = new String("Spring");
    s1.concat("SUMMER");
    String s2 = s1.concat("Fall");
    s1 = s1.concat("Winter");
    System.out.println(s1);
    System.out.println(s2);
}
Important: Calling concat() does not modify the original String. Assigning the returned String to a variable is necessary if the new value is required.

The source diagrams on the relevant pages illustrate references to String objects in the Heap and String Constant Pool and show the additional objects produced by runtime concatenation.

8. String vs StringBuffer vs StringBuilder

FeatureStringStringBufferStringBuilder
MutabilityImmutableMutableMutable
Thread safetyImmutableThread-safe / synchronizedNot thread-safe by default
PerformanceSuitable when content is fixedRelatively slowerRelatively faster
SynchronizationNot applicableMethods are synchronizedMethods are non-synchronized
IntroducedCore JavaJava 1.0Java 1.5
  • If content is fixed and does not change frequently, use String.
  • If content changes frequently and thread safety is required, use StringBuffer.
  • If content changes frequently and thread safety is not required, use StringBuilder.

9. String intern()

The intern() method returns a canonical representation of a String. It checks the String Pool for a String with the same contents and returns the pooled reference when available.

public class StringInternExample {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello");

        System.out.println("str1 == str2: " + (str1 == str2));
        System.out.println("str1 == str3: " + (str1 == str3));
        System.out.println("str1 == str3.intern(): " + (str1 == str3.intern()));
    }
}
Expected results:
str1 == str2 → true
str1 == str3 → false
str1 == str3.intern() → true

10. Immutable Objects and Immutable Classes

An immutable object does not change its internal state after creation. It effectively becomes a read-only object after instantiation.

Rules for an immutable class

  1. Declare the class final.
  2. Make all fields final.
  3. Do not provide setter methods that can change the object's state.
  4. Do not allow the this reference to escape during construction.
  5. Maintain exclusive access to mutable referenced objects such as arrays, collections and mutable date objects.
  6. Keep mutable references private and do not expose them directly to callers.
Examples mentioned in the notes include immutable numeric types such as Integer, Float and BigDecimal.

11. Var-args

The notes explain that before Java 1.5, methods could not directly declare a variable number of arguments. Var-args were introduced in Java 1.5 to solve this problem.

Syntax

Method(int... a)

A var-args method can be called with zero or more arguments:

Method();
Method(10, 20);
Method(10, 20, 30);
Method(10, 20, 30, 40);

Internally, a var-args parameter is treated as a one-dimensional array.

Method(int... a)

// conceptually handled as
int[] a

Example iteration:

int total = 0;

for (int x1 : x) {
    total = total + x1;
}

12. Primary Considerations for a User-Defined Key

  1. If a class overrides equals(), it must override hashCode().
  2. If two objects are equal, their hashCode values must also be equal.
  3. If a field is not used in equals(), it should not be used in hashCode().

13. String Programs

The following programs are included in the source notes.

Reverse String char[] Conversion Character Count byte[] Conversion Permutations Case Conversion subSequence() Palindrome Remove Character Special Reverse

14. Reverse of a Given String

public class StringReverse {
    public static void main(String[] args) {
        String str = "Hello, World!";
        char[] charArray = str.toCharArray();

        int start = 0;
        int end = charArray.length - 1;

        while (start < end) {
            char temp = charArray[start];
            charArray[start] = charArray[end];
            charArray[end] = temp;
            start++;
            end--;
        }

        String reversedStr = new String(charArray);
        System.out.println("Reversed String: " + reversedStr);
    }
}

15. Convert String to Character Array

public class StringToCharArray {
    public static void main(String[] args) {
        String str = "Hello, World!";
        char[] charArray = str.toCharArray();

        for (char c : charArray) {
            System.out.print(c + " ");
        }
    }
}

16. Count Occurrences of a Character

public class CountChar {
    public static void main(String[] args) {
        String str = "Hello, World!";
        char ch = 'o';
        int count = 0;

        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == ch) {
                count++;
            }
        }

        System.out.println(
            "Number of occurrences of " + ch + " in " + str + " is: " + count
        );
    }
}

17. Convert String to Byte Array

public class StringToByteArray {
    public static void main(String[] args) {
        String str = "Hello, World!";
        byte[] byteArray = str.getBytes();

        System.out.println("String: " + str);
        System.out.println("Byte array: " + Arrays.toString(byteArray));
    }
}

18. Print All Permutations of a String

public class StringPermutations {
    public static void main(String[] args) {
        String str = "abc";
        int length = str.length();
        permute(str, 0, length - 1);
    }

    private static void permute(String str, int left, int right) {
        if (left == right) {
            System.out.println(str);
        } else {
            for (int i = left; i <= right; i++) {
                str = swap(str, left, i);
                permute(str, left + 1, right);
                str = swap(str, left, i);
            }
        }
    }

    private static String swap(String str, int i, int j) {
        char temp;
        char[] charArray = str.toCharArray();

        temp = charArray[i];
        charArray[i] = charArray[j];
        charArray[j] = temp;

        return String.valueOf(charArray);
    }
}

19. String Upper Case / Lower Case

public class StringCase {
    public static void main(String[] args) {
        String str = "Hello, World!";

        String strUpper = str.toUpperCase();
        String strLower = str.toLowerCase();

        System.out.println("Original string: " + str);
        System.out.println("Uppercase string: " + strUpper);
        System.out.println("Lowercase string: " + strLower);
    }
}

20. String subSequence() Method

public class SubSequenceExample {
    public static void main(String[] args) {
        String str = "Hello, World!";

        CharSequence subSequence = str.subSequence(0, 5);

        System.out.println("Original string: " + str);
        System.out.println("Subsequence: " + subSequence);
    }
}

21. Check Whether a String is a Palindrome

public static boolean isPalindrome(String str) {
    // Remove all non-alphanumeric characters and convert to lowercase
    str = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();

    // Check whether the string is the same forwards and backwards
    for (int i = 0; i < str.length() / 2; i++) {
        if (str.charAt(i) != str.charAt(str.length() - i - 1)) {
            return false;
        }
    }

    return true;
}

22. Remove a Given Character from a String

public static String removeCharacter(String str, char ch) {
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);

        if (c != ch) {
            sb.append(c);
        }
    }

    return sb.toString();
}

23. Special Reverse String Program

public class SpecialReverse {
    public static void main(String[] args) {
        String input = "sree";
        String original = input;
        String reversed = specialReverse(input, input);
    }

    public static String specialReverse(
            String givenString, String reversedString) {

        int length = givenString.length();
        char c;

        StringBuffer dest = new StringBuffer(length);
        StringBuffer possibleString = new StringBuffer(length);

        for (int i = length - 1; i >= 0; i--) {
            c = givenString.charAt(i);
            dest.append(c);
        }

        reversedString = dest.toString();

        possibleString.append(givenString);
        possibleString.append(reversedString);

        if (reversedString.equals(givenString)) {
            System.out.println(
                " '" + givenString + "' is a polyndrom string"
            );
        } else {
            System.out.println(
                "\n polyndrom string is : '" + possibleString + "' "
            );
        }

        return possibleString.toString();
    }
}
Source terminology preserved: The original notes use the spelling “polyndrom” in the displayed program/message.

Quick Revision

TopicRemember
StringImmutable
StringBufferMutable and synchronized
StringBuilderMutable and non-synchronized
equals()String content comparison
==Reference comparison
intern()Returns canonical pooled String reference
Var-argsVariable number of arguments; internally represented as an array
Immutable classFinal class, final state, no mutating setters, safe handling of mutable references