r/JavaProgramming • u/Individual-Corgi6109 • Aug 19 '26
How to prove java string immutability via code? Asked in recent interview.
Interviewer asked me to prove that Java Strings are immutable.
I couldn't bring myself to simply concatenate a String and print it, because concat() returns a new String rather than modifying the original.
Then I thought hash codes might help, but the interviewer stopped me there, pointing out that different Strings can have different hash codes anyway.
If we could access Java's underlying memory directly, I could prove that the original String object remains unchanged. But without going that deep, is there any other convincing way to demonstrate String immutability?
What would you have answered?
4
u/LetUsSpeakFreely Aug 19 '26
It was a trick question. The string class offers no mutators. Due to encapsulation there is no way to directly access the internal data.
The best way i could prove it is something like:
String a = "abc";
System.out.println(a == a.replace("b","d"));
That should print false ad they're two different objects.
1
u/repeating_bears Aug 20 '26
All that proves is that 'replace' returns a new instance. There could be another method 'replaceInPlace' which does the modification in-place.
1
u/LetUsSpeakFreely Aug 20 '26
But there isn't. That's the whole point. There are no direct mutators. Every method that has the veneer of a mutator actually returns a new instance.
If an interviewer were asking me such a braindead question, that's how i would go about answering it.
1
u/repeating_bears Aug 20 '26
Well exactly, the question is stupid. But you said "The best way i could prove it" and I was just commenting that that isn't a proof.
You've shown that a single method returns a new instance for some specific arguments. Another method might modify the current instance, or 'replace' might modify the current instance if you give it different arguments - that would be a stupid implementation, but a proof cannot discount a possibility just because it is stupid.
The only proof is to exhaustively check every method's implementation for mutations. If they expect you to treat String as a black box then it's not answerable because there are infinite possible arguments.
I'm not sure what answer would satisfy the interviewer. We both agree they're an idiot, so they could be expecting almost anything
1
u/LetUsSpeakFreely Aug 20 '26
The only other thing i can think of is pointing to the documentation that explicitly states Strings are immutable.
3
u/sin_cara_00 Aug 20 '26
First you tell me the method to mutate the string, if you can’t - they’re immutable 😂
3
u/repeating_bears Aug 19 '26
Bad question
To prove immutability in a black box test, you would need to call all methods with all possible arguments, under all conditions. This is an infinite number of permutations (for all classes, not just String).
Imagine the 'length' method had some random side effect which mutated the string under some extremely specific condition
public int length() {
var now = Instant.now();
// on a specific but random millisecond change the value for some unknown reason
if (now.toEpochMilli() == 11245135) {
this.value[0] = 'a';
}
// this is the actual impl
return value.length >> coder();
}Obviously that would be stupid and we know it doesn't do that, but hopefully it demonstrates that a black box "proof" is not possible. For this code to apply any observable mutation, you'd have to know to test it on some specific millisecond. At all other times it has no side effect.
The only way to prove String is immutable is to look at the implementation and observe that no mutations are applied. The string class is 5000 LOC so I guess they are not wanting you to do that.
In practice, the way to prove that String is immutable is to look at the javadoc which tells you that it's immutable.
-2
Aug 19 '26
[removed] — view removed comment
4
u/repeating_bears Aug 19 '26
Just downvote in future. I don't need to get a notification for this pointless shit if you can't be arsed to explain
-2
1
u/ExtraTNT Aug 19 '26
So, if you care about immutability of strings that much, that it’s more important, than the knowing, that your code works fine: use haskell…
I do like haskell…
1
u/romulusnr Aug 20 '26
I was thinking something like
String a = "foo";
String b = a;
String a = "bar";
a.equals(b) == false;But that doesnt prove it. Or does it? The fact you can't modify the pointed value because changes to the String object are re-pointed implies functional immutability.
1
1
Aug 20 '26
[removed] — view removed comment
1
1
u/repeating_bears Aug 20 '26
In order,
String a = "foo";Variable 'a' points to an instance of String with the content "foo"
String b = a;Variable 'b' points to that same instance
// have to remove the string declaration // as you cannot redeclare variable 'a' /*String*/ a = "bar";Variable 'a' points to a different instance of String with the content "bar"
a.equals(b)Content "foo" is not the same as content "bar". Whether the instance is the same or different is irrelevant.
1
u/_MeTTeO_ Aug 20 '26
Immutable class has special properties: cannot be extended (class is final), all the fields are final and immutable.
I would say there are 2 ways: - reflection to detect above properties - inspecting source / byte code of String class
1
u/repeating_bears Aug 20 '26
String's content is a 'final byte[]' and Java arrays are naturally mutable.
Strings can be still considered immutable if no methods (except the constructor) make any changes to that byte array, but reflection doesn't have the information to know how the byte array is accessed.
Reading the source or bytecode is the only way
1
u/_MeTTeO_ Aug 20 '26
Yes, I stopped at "all the fields are final and immutable" and added "effectively immutable" but removed it to not complicate things.
1
u/idontlikegudeg Aug 21 '26
A little more complex. String does indeed have mutable fields, i.e., for lazy hash code calculation. So no mutable state + final class -> class is immutable, but the other direction is not necessarily true. You could even observe the changed state using reflection.
But there is no way to observe the changed state using only the public API of the class (there's a theoretical small loophole: you could observe changes in runtime when calling hashCode()).
1
u/am_Snowie Aug 20 '26 edited Aug 20 '26
Build a long ass string character by character with regular concatenation operation a million times, a mutable string wouldn't take more space than the length of the string. I can't think of any other idea, or maybe declare two different variables and use the same string value like "Hello", since it's immutable, there's a chance that java reuses it, so both variable point to the same string, so == operation would return true if they're immutable and they're the same object.
// This will return true if they share the object.
class Main {
public static void main(String[] args) {
String a = "Hello";
String b = "Hello";
System.out.println(a == b); // true
System.out.println(a == b + " "); // false
}
}You can use this property and try to prove they're immutable. If you mutate b and the a == b returns true, yes it's mutable, it's immutable otherwise.
1
1
u/rb_arindam Aug 21 '26
he wasn't looking for ways to mutate string.
he was looking for your knowledge on mutability and your understanding of == operator.
1
1
u/hwglitch Aug 22 '26
What? But you can prove that Java Strings are mutable. Here's the code:// MutableStringTest.javavoid main() {
String str = "Java";
IO.println(str); // prints "Java"
try {Field valueField = String.class.getDeclaredField("value");valueField.setAccessible(true);byte[] internalArray = (byte[]) valueField.get(str);internalArray[0] = (byte) 'O';internalArray[1] = (byte) 'o';internalArray[2] = (byte) 'p';internalArray[3] = (byte) 's';
} catch (Exception ex) {IO.println(ex);return;
}
IO.println(str); // prints "Oops"}
Run on OpenJDK 25 with
java --add-opens java.base/java.lang=ALL-UNNAMED ./MutableStringTest.java
P.S. Even Google knows it.
1
1
Aug 19 '26 edited Aug 19 '26
[removed] — view removed comment
3
1
8
u/mtimmermans Aug 19 '26
Stupid question. There are no methods that mutate the string, and no mutable fields, therefore it's immutable.