A collection of classic “what does this print?” questions about strings, the pool, boxing and constant folding — each verified.
== on strings
public class Main {
public static void main(String[] args) {
String a = "java";
String b = "java"; // same pooled literal
String c = new String("java"); // a new heap object
String d = "ja" + "va"; // compile-time constant → folded to "java"
String part = "ja";
String e = part + "va"; // runtime concatenation → new object
final String fpart = "ja";
String f = fpart + "va"; // final + literal is a constant → folded
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(a == f);
System.out.println(a == e.intern());
System.out.println(a.equals(c));
}
}true
false
true
false
true
true
true| Expression | Pooled? | Why |
|---|---|---|
"java" | Yes | Every string literal is interned in the pool |
new String("java") | No | new always creates a fresh heap object |
"ja" + "va" | Yes | Constant expression, folded by javac |
part + "va" (non-final part) | No | Computed at run time (StringConcatFactory / StringBuilder) |
fpart + "va" (final with constant initialiser) | Yes | fpart is a constant variable, so the whole expression is constant |
s.intern() | Yes | Returns the pooled instance, adding it if absent |
How many objects does new String("hello") create?
Integer cache and boxing
public class Main {
public static void main(String[] args) {
Integer a = 127, b = 127;
Integer c = 128, d = 128;
System.out.println(a == b); // cached: -128..127
System.out.println(c == d); // two different objects
System.out.println(c.equals(d));
Long big = 127L;
System.out.println(big.equals(127)); // Integer vs Long → false
System.out.println(big == 127); // unboxed numeric comparison → true
Integer missing = null;
try {
int n = missing; // auto-unboxing null
System.out.println(n);
} catch (NullPointerException ex) {
System.out.println("NPE on unboxing");
}
boolean flag = true;
try {
int r = flag ? missing : 0; // ternary unboxes `missing`
System.out.println(r);
} catch (NullPointerException ex) {
System.out.println("NPE in ternary");
}
}
}true
false
true
false
true
NPE on unboxing
NPE in ternaryConcatenation and char arithmetic
public class Main {
public static void main(String[] args) {
System.out.println("a" + 1 + 2); // left to right: ("a" + 1) + 2
System.out.println(1 + 2 + "a"); // (1 + 2) + "a"
System.out.println('a' + 'b'); // char + char → int
System.out.println("" + 'a' + 'b');
System.out.println((char) ('a' + 1));
System.out.println(Math.abs(Integer.MIN_VALUE)); // overflow: no positive counterpart
System.out.println(0.1 + 0.2);
}
}a12
3a
195
ab
b
-2147483648
0.30000000000000004String + in a loop
Each s += x creates a brand-new string and copies everything so far — O(n²) for n appends. Inside loops use a StringBuilder (single-expression concatenations are fine: the compiler optimises them).
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) {
sb.append(i).append(',');
}
sb.setLength(sb.length() - 1); // drop the trailing comma
System.out.println(sb);
System.out.println(String.join(",", "a", "b", "c")); // often simplest
}
}0,1,2,3,4
a,b,cOther traps
public class Main {
public static void main(String[] args) {
String s = "hello";
s.toUpperCase(); // result discarded
System.out.println(s);
s = s.toUpperCase();
System.out.println(s);
}
}hello
HELLOswitch on strings and null
A switch on a String compiles to a switch on hashCode() followed by equals(). A null selector throws NullPointerException — unless (Java 21) you add case null.
public class Main {
static String classic(String cmd) {
switch (cmd) {
case "start": return "starting";
case "stop": return "stopping";
default: return "unknown";
}
}
static String modern(String cmd) {
return switch (cmd) {
case null -> "no command"; // Java 21
case "start" -> "starting";
default -> "unknown";
};
}
public static void main(String[] args) {
System.out.println(classic("stop"));
try {
classic(null);
} catch (NullPointerException e) {
System.out.println("NPE from classic switch");
}
System.out.println(modern(null));
}
}stopping
NPE from classic switch
no commandWhy is String immutable in Java?
What does intern() do, and should you use it?