Accessors, Mutators, and the Immutable String Class
Accessors and Mutators
Accessors:
Any method that does not alter the object's member variables or, by extension, the state of the object. The state of the object remains exactly the same before and after the method call.
Simplest form: A getter method. Getters simply return the value of a member variable without changing it.
Example from Student Class: The
canGraduatemethod is an accessor. It reads values like GPA and graduation year but does not modifyid,gpa,graduationYear, orstartDate.Used for accessing information an object holds without changing it.
Mutators:
Any method that does alter the object's member variables or, by extension, the state of the object. The state of the object after the method call is different from what it was before.
Simplest form: A setter method (e.g.,
setID,setGPA). These methods change the value of one or more member variables.Used for changing the data or state of an object.
Immutable Classes
A class is referred to as immutable if it contains absolutely no mutator methods.
This means that once an object of an immutable class is created, its internal data (state) cannot be altered or changed. It is "untouchable" after creation.
You can access the data, but you cannot change it.
The concept of immutability is common in Java, and understanding it provides significant context when working with various classes and documentation.
The String Class: A Deeper Look
Non-Primitive Type:
Stringis not one of Java's eight primitive data types (e.g.,int,boolean,char). Therefore,Stringis a non-primitive type, implying it has an associated Java class.Storing Addresses: A
Stringvariable (e.g.,String s;) stores an address (pointer) to aStringobject, not the characters themselves. This is similar to how array variables work.String Object Structure: A
Stringobject, residing in the heap, conceptually contains an array ofcharvalues representing the string's text.Each
chartypically consumes bytes of memory. For example, "hello world" (11 characters: ) consumes bytes of memory just for its characters.Strings can be memory-intensive, leading to Java's optimization strategies.
Creating String Objects
There are two primary ways to create String objects, with differing implications for how they are stored in memory:
Using the
newoperator:Example:
String s = new String("hello world");The
newoperator instructs the Java Virtual Machine (JVM) to allocate a new, unused chunk of memory in the heap (outside the string pool) for aStringobject.A
Stringconstructor is called to initialize this new object with the provided characters.The address of this newly created object is then stored in the
Stringvariables.
Assigning a String literal:
Example:
String s = "hello world";A string literal is a hard-coded, provided text value enclosed in double quotes.
Purpose: Java employs a special memory region within the heap called the string pool to optimize storage of string literals.
Algorithm for Literals:
Check the pool: When a string literal is assigned, Java first checks if an object with that exact same sequence of characters already exists in the string pool.
If found: Java returns the address of the existing matching string object from the pool. No new object is created.
If not found: Java creates a new string object in the string pool, stores the literal's characters there, and returns the address of this new object.
The == Operator vs. .equals() Method for Strings
==Operator Behavior:The
==operator always compares the values stored in the variables.For primitive types (e.g.,
int a = 5; int b = 5;),a == bcompares the actual numerical values and returnstrueif they are the same.For non-primitive (reference) types like
String, the variables store addresses. Therefore,==compares whether the addresses stored in the variables are identical (i.e., whether both variables point to the exact same object in memory).It does not compare the content (characters) of the strings.
Demonstration Scenarios:
String s1 = "hello world"; String s2 = "hello world"; System.out.println(s1 == s2);Execution:
s1 = "hello world";(literal): Java checks the string pool. "hello world" is not present, so a new object is created in the pool at address.s1stores.s2 = "hello world";(literal): Java checks the string pool. "hello world" is present at address. Java returns this existing address.s2stores.
Result:
true(becauses1ands2both store the address, pointing to the same object).
String s1 = "hello world"; String s2 = new String("hello world"); System.out.println(s1 == s2);Execution:
s1 = "hello world";(literal): A new object is created in the string pool at address.s1stores.s2 = new String("hello world");(usingnew): Java bypasses the string pool. A new object is created in the general heap (outside the pool) at a different address, say.s2stores.
Result:
false(becauses1storesands2stores, which are different addresses).
java String s1 = new String("hello world"); String s2 = new String("hello world"); System.out.println(s1 == s2);Execution:
s1 = new String("hello world");(usingnew): A new object is created in the general heap at address.s1stores.s2 = new String("hello world");(usingnew): Another new object is created in the general heap at a different address, say.s2stores.
Result:
false(becauses1storesands2stores, which are different addresses, even though their contents are identical).
.equals()Method:To compare the actual sequence of characters (content) of two
Stringobjects, use the.equals()method:s1.equals(s2).This method performs a character-by-character comparison of the string's content.
String Immutability and its Importance
The
Stringclass is an excellent example of an immutable class in Java.This design choice means that once a
Stringobject is created, its sequence of characters cannot be changed.Why is this important? If multiple
Stringvariables point to the sameStringobject, and that object were mutable, changing the string's content via one variable would inadvertently affect all other variables pointing to it. Immutability prevents this issue.Immutable Methods (Accessors): All methods in the
Stringclass are accessors; there are no mutators.For example,
concat()andreplace()methods might seem to modify strings.However, they do not change the original
Stringobject they are called on. Instead, they return a newStringobject containing the concatenated or replaced characters. The original string remains unaltered.This ensures data integrity and predictable behavior when working with strings. There are no methods in the String API that allow you to change the text content of an existing String object.
String is one of many immutable classes provided by Java, emphasizing its reliability and safety against unintended modifications.