Skip to main content

English + German

English stays on the page. Click the button to show the German text under each question.

Java Fundamentals

These questions open most backend interviews. Weak equals/hashCode, immutability, or exception answers are an early filter — Spring never saves you here.

Practice with the four-part answer.

Deutsch

Java-Grundlagen

Diese Fragen stehen am Anfang der meisten Backend-Interviews. Schwache Antworten zu equals/hashCode, Immutability oder Exceptions sind ein früher Filter — Spring rettet dich hier nicht.

Übe mit der Antwort in vier Teilen.

1. How does Java pass arguments: by value or by reference?

Deutsch

Wie übergibt Java Argumente: by value oder by reference?

Level: Junior · Listen for: everything is pass-by-value; object references are copied

Niveau: Junior · Darauf hören sie: alles ist pass-by-value; Objektreferenzen werden kopiert

Model answer

Java is pass-by-value. For primitives the value is copied. For objects the reference is copied, so the callee can mutate the same object but cannot reassign the caller's variable.

void rename(User user) {
user.setName("Ada"); // visible to caller
user = new User("Bob"); // caller's variable unchanged
}

Follow-ups

  • What happens if the parameter is final?
  • Why do people still say “pass by reference”?

Trap: “Objects are passed by reference.” That is the C++ meaning, not Java’s.

Memory sentence: Java copies the value; for objects that value is the reference.

Musterantwort

Java ist pass-by-value. Bei Primitives wird der Wert kopiert. Bei Objekten wird die Referenz kopiert: die aufgerufene Methode kann dasselbe Objekt mutieren, die Variable des Aufrufers aber nicht neu zuweisen.

Nachfragen

  • Was passiert, wenn der Parameter final ist?
  • Warum sagen Leute trotzdem „pass by reference“?

Falle: „Objekte werden by reference übergeben.“ Das ist die C++-Bedeutung, nicht die von Java.

Merksatz: Java kopiert den Wert; bei Objekten ist dieser Wert die Referenz.

2. What is the equals / hashCode contract?

Deutsch

Was ist der equals/hashCode-Contract?

Level: Mid · Listen for: equal objects must have the same hash; use both as keys

Niveau: Mid · Darauf hören sie: gleiche Objekte müssen denselben Hash haben; beides als Keys nutzen

Model answer

If a.equals(b) is true, a.hashCode() and b.hashCode() must be equal. The reverse is not required: different objects may collide on a hash.

HashMap and HashSet first bucket by hash, then confirm with equals. Break the contract and you lose keys, get duplicates, or never find an entry.

Prefer business keys you control. If you include mutable fields, a later mutation moves the logical object while the map still looks in the old bucket.

Follow-ups

  • Why should equals be consistent with compareTo?
  • What does == vs equals mean for String?

Trap: implementing equals and forgetting hashCode, or using a mutable id that is null before persist and set after.

Memory sentence: Equal objects share a hash; maps trust that before they trust equals.

Musterantwort

Wenn a.equals(b) true ist, müssen a.hashCode() und b.hashCode() gleich sein. Die Gegenrichtung gilt nicht: verschiedene Objekte dürfen auf demselben Hash kollidieren.

HashMap und HashSet legen zuerst den Bucket per Hash fest und prüfen dann mit equals. Brichst du den Contract, verlierst du Keys, bekommst Duplikate oder findest einen Eintrag nie wieder.

Bevorzuge Business-Keys, die du kontrollierst. Nimmst du mutable Felder auf, verschiebt eine spätere Mutation das logische Objekt, während die Map noch im alten Bucket sucht.

Nachfragen

  • Warum soll equals zu compareTo konsistent sein?
  • Was bedeutet == vs equals bei String?

Falle: equals implementieren und hashCode vergessen, oder eine mutable id nutzen, die vor dem persist null ist und danach gesetzt wird.

Merksatz: Gleiche Objekte teilen sich einen Hash; Maps vertrauen dem Hash, bevor sie equals fragen.

3. Why is String immutable, and why does that matter?

Deutsch

Warum ist String immutable, und warum ist das wichtig?

Level: Junior · Listen for: cache, security, intern pool, thread safety

Niveau: Junior · Darauf hören sie: Cache, Security, Intern-Pool, Thread-Safety

Model answer

String is a final class whose character data cannot change after construction. That makes strings safe as map keys, usable as class names and credentials, shareable across threads, and internable.

Concatenation in a loop with + still creates many intermediate strings. Use StringBuilder for that. StringBuffer is the synchronized variant — almost never what you want in new code.

Follow-ups

  • What does String.intern() do, and when is it a problem?
  • How do string literals end up in the pool?

Trap: using == to compare strings, or saying immutability means “strings live on the stack”.

Memory sentence: Immutable strings are shareable and safe as keys; builders exist for repeated mutation.

Musterantwort

String ist eine final Klasse, deren Zeichendaten sich nach der Konstruktion nicht mehr ändern. Deshalb sind Strings sichere Map-Keys, taugen als Klassennamen und Credentials, sind über Threads hinweg teilbar und können interned werden.

Konkatenation in einer Schleife mit + erzeugt trotzdem viele Zwischen-Strings. Dafür nimmst du StringBuilder. StringBuffer ist die synchronized Variante — in neuem Code fast nie das, was du willst.

Nachfragen

  • Was macht String.intern(), und wann wird es zum Problem?
  • Wie landen String-Literale im Pool?

Falle: Strings mit == vergleichen, oder Immutability mit „Strings leben auf dem Stack“ verwechseln.

Merksatz: Immutable Strings sind teilbar und sichere Keys; Builder gibt es für wiederholte Mutation.

4. How do you make a class immutable?

Deutsch

Wie machst du eine Klasse immutable?

Level: Mid · Listen for: final fields, no setters, defensive copies, no leaking mutables

Niveau: Mid · Darauf hören sie: final Fields, keine Setter, defensive Copies, keine Mutables nach außen

Model answer

An immutable type cannot change after construction, from any reference.

Recipe: class final (or sealed), fields private final, no setters, all state set in the constructor, defensive copies of mutable inputs and outputs (Date, collections, arrays). Do not return the internal list.

Records give this for shallow immutability. A record that holds an ArrayList is still mutable unless you copy the list.

Follow-ups

  • Shallow vs deep immutability?
  • Why are setter-based JavaBeans a poor domain model?

Trap: final on the field only. The field cannot be reassigned, but the object it points to can still change.

Memory sentence: final stops reassignment; immutability also stops mutation through nested objects.

Musterantwort

Ein immutable Typ kann sich nach der Konstruktion nicht mehr ändern — über keine Referenz.

Rezept: Klasse final (oder sealed), Felder private final, keine Setter, gesamter State im Konstruktor gesetzt, defensive Copies von mutable Inputs und Outputs (Date, Collections, Arrays). Die interne Liste nicht zurückgeben.

Records liefern das für shallow Immutability. Ein Record, der eine ArrayList hält, ist trotzdem mutable, solange du die Liste nicht kopierst.

Nachfragen

  • Shallow vs deep Immutability?
  • Warum sind setter-basierte JavaBeans ein schlechtes Domain-Modell?

Falle: nur final am Feld. Das Feld kann nicht neu zugewiesen werden, das Objekt dahinter aber schon.

Merksatz: final stoppt die Neu-Zuweisung; Immutability stoppt auch Mutation über verschachtelte Objekte.

5. Overloading vs overriding?

Deutsch

Overloading vs Overriding?

Level: Junior · Listen for: compile-time vs runtime; signatures; @Override

Niveau: Junior · Darauf hören sie: Compile-Time vs Runtime; Signaturen; @Override

Model answer

Overloading is several methods with the same name and different parameter types. The compiler picks the match.

Overriding replaces a superclass instance method with the same signature. The JVM picks the implementation from the runtime type.

Static methods hide, they do not override. Private methods do not override. Return types may be covariant. Use @Override so a signature mismatch fails the build.

Follow-ups

  • What is the output if an overloaded method takes Object vs String and you pass null?
  • Can you override with a narrower checked exception?

Trap: expecting runtime dispatch for overloads.

Memory sentence: Overload is compile time; override is runtime on instance methods.

Musterantwort

Overloading heißt: mehrere Methoden mit gleichem Namen und unterschiedlichen Parametertypen. Den Treffer sucht der Compiler.

Overriding heißt: eine Instanzmethode der Superklasse mit derselben Signatur ersetzen. Die JVM nimmt die Implementierung vom Runtime-Typ.

Static Methods machen hiding, kein Override. Private Methods ebenfalls nicht. Rückgabetypen dürfen kovariant sein. Nimm @Override, damit eine falsche Signatur den Build bricht.

Nachfragen

  • Was kommt raus, wenn eine überladene Methode Object vs String nimmt und du null übergibst?
  • Kannst du beim Override eine engere checked Exception deklarieren?

Falle: bei Overloads Runtime-Dispatch erwarten.

Merksatz: Overload ist Compile-Time; Override ist Runtime auf Instanzmethoden.

6. Interface vs abstract class? Where do default methods fit?

Deutsch

Interface vs abstrakte Klasse? Wo passen Default Methods hin?

Level: Mid · Listen for: multiple inheritance of type vs shared state

Niveau: Mid · Darauf hören sie: Mehrfachvererbung vom Typ vs geteilter State

Model answer

Use an interface for a capability (Payable, Repository). A class can implement many. Interfaces can have default and static methods, but they should not grow into hidden base classes.

Use an abstract class when you share state and a template of behavior, and you want a single is-a hierarchy.

Default methods exist so APIs can evolve without breaking implementors (List.sort). If two interfaces provide the same default method, the class must resolve the conflict.

Follow-ups

  • Abstract class with only abstract methods vs interface?
  • Why not put everything in a default method?

Trap: “interface cannot have methods” — outdated since Java 8.

Memory sentence: Interfaces are capabilities; abstract classes are shared state plus a template.

Musterantwort

Nutze ein Interface für eine Capability (Payable, Repository). Eine Klasse kann viele implementieren. Interfaces dürfen default und static Methoden haben, sollen aber nicht zu versteckten Basisklassen anwachsen.

Nutze eine abstrakte Klasse, wenn du State und ein Template von Verhalten teilst und eine einzige is-a-Hierarchie willst.

Default Methods gibt es, damit APIs wachsen können, ohne Implementoren zu brechen (List.sort). Liefern zwei Interfaces dieselbe Default Method, muss die Klasse den Konflikt auflösen.

Nachfragen

  • Abstrakte Klasse nur mit abstrakten Methoden vs Interface?
  • Warum nicht alles in eine Default Method stecken?

Falle: „Ein Interface kann keine Methoden haben“ — überholt seit Java 8.

Merksatz: Interfaces sind Capabilities; abstrakte Klassen sind geteilter State plus Template.

7. Checked vs unchecked exceptions? What should a REST service throw?

Deutsch

Checked vs unchecked Exceptions? Was soll ein REST-Service werfen?

Level: Mid · Listen for: recoverability, not “checked is better”

Niveau: Mid · Darauf hören sie: ob du recoveren kannst, nicht „checked ist besser“

Model answer

Checked exceptions are part of the API contract (IOException). Callers must catch or declare them. Unchecked (RuntimeException) signal programming errors or domain failures you usually cannot handle locally.

In Spring services I prefer unchecked domain exceptions (OrderNotFoundException) and map them in @ControllerAdvice to HTTP status codes. Wrapping every repository call in checked exceptions makes service code noisy without adding recovery.

Catch at the boundary where you can actually compensate: retry, fallback, or user message. Do not swallow and return null.

Follow-ups

  • Error vs Exception?
  • Why does Spring’s DataAccessException hierarchy exist?

Trap: “never use runtime exceptions” or empty catch (Exception e) {}.

Memory sentence: Checked forces a decision at compile time; services usually throw unchecked and translate at the HTTP boundary.

Musterantwort

Checked Exceptions gehören zum API-Contract (IOException). Caller müssen sie fangen oder deklarieren. Unchecked (RuntimeException) signalisieren Programmierfehler oder Domain-Fehler, die du lokal meist nicht behandeln kannst.

In Spring-Services bevorzuge ich unchecked Domain-Exceptions (OrderNotFoundException) und mappe sie in @ControllerAdvice auf HTTP-Statuscodes. Jeden Repository-Aufruf in checked Exceptions zu wrappen macht den Service-Code unübersichtlich, ohne Recovery zu bringen.

Fang an der Grenze, an der du wirklich kompensieren kannst: Retry, Fallback oder Meldung an den User. Nicht schlucken und null zurückgeben.

Nachfragen

  • Error vs Exception?
  • Warum gibt es Springs DataAccessException-Hierarchie?

Falle: „nie Runtime Exceptions nutzen“ oder leeres catch (Exception e) {}.

Merksatz: Checked zwingt zur Compile-Time-Entscheidung; Services werfen meist unchecked und übersetzen an der HTTP-Grenze.

8. try-with-resources vs finally?

Deutsch

try-with-resources vs finally?

Level: Junior · Listen for: AutoCloseable, suppressed exceptions

Niveau: Junior · Darauf hören sie: AutoCloseable, suppressed Exceptions

Model answer

try-with-resources closes AutoCloseable resources in reverse order, even if the body throws. That is the default for streams, connections, and files.

finally still exists for cleanup that is not a closeable. If both the body and close() throw, the body’s exception is primary and close() is suppressed (Throwable.getSuppressed()).

Follow-ups

  • Why can a finally return hide the original exception?
  • Does Spring close EntityManager for you?

Trap: returning from finally, or closing a Spring-managed resource you do not own.

Memory sentence: Prefer try-with-resources; finally is for non-closeable cleanup.

Musterantwort

try-with-resources schließt AutoCloseable-Ressourcen in umgekehrter Reihenfolge, auch wenn der Rumpf wirft. Das ist der Default für Streams, Connections und Dateien.

finally bleibt für Aufräumen, das kein Closeable ist. Werfen Rumpf und close() beide, ist die Exception des Rumpfs primär und close() wird suppressed (Throwable.getSuppressed()).

Nachfragen

  • Warum kann ein return in finally die ursprüngliche Exception verstecken?
  • Schließt Spring den EntityManager für dich?

Falle: aus finally returnen, oder eine von Spring verwaltete Ressource schließen, die dir nicht gehört.

Merksatz: Lieber try-with-resources; finally ist für Aufräumen, das nicht closeable ist.

9. What is type erasure? What survives at runtime?

Deutsch

Was ist Type Erasure? Was bleibt zur Runtime übrig?

Level: Mid · Listen for: List<String> is List at runtime; bounds; reified arrays

Niveau: Mid · Darauf hören sie: List<String> ist zur Runtime List; Bounds; reified Arrays

Model answer

Generics are a compile-time tool. The compiler inserts casts and then erases type parameters. At runtime List<String> and List<Integer> are both List.

You cannot new T(), create T[] cleanly, or overload two methods that differ only by a type parameter. You can inspect bounds (List<? extends Number>) and you still have Class objects for raw types.

Arrays are reified and covariant, which is why Object[] tricks are unsafe. Prefer lists.

Follow-ups

  • PECS: producer-extends, consumer-super?
  • Why is instanceof List<String> illegal?

Trap: if (list instanceof List<String>) or expecting getClass() to show the parameter.

Memory sentence: Generics disappear at runtime; the compiler already proved the casts.

Musterantwort

Generics sind ein Compile-Time-Werkzeug. Der Compiler fügt Casts ein und löscht (erases) dann die Type Parameters. Zur Runtime sind List<String> und List<Integer> beide List.

Du kannst nicht new T(), kein sauberes T[] erzeugen und nicht zwei Methoden überladen, die sich nur im Type Parameter unterscheiden. Bounds kannst du inspizieren (List<? extends Number>), und Class-Objekte für Raw Types gibt es weiterhin.

Arrays sind reified und kovariant — deshalb sind Object[]-Tricks unsicher. Lieber Listen.

Nachfragen

  • PECS: producer-extends, consumer-super?
  • Warum ist instanceof List<String> illegal?

Falle: if (list instanceof List<String>) oder erwarten, dass getClass() den Parameter zeigt.

Merksatz: Generics verschwinden zur Runtime; die Casts hat der Compiler schon bewiesen.

10. When do you use Optional? When do you not?

Deutsch

Wann nutzt du Optional? Wann nicht?

Level: Mid · Listen for: return types, not fields, not parameters, not in entities

Niveau: Mid · Darauf hören sie: Rückgabetyp, nicht Felder, nicht Parameter, nicht in Entities

Model answer

Optional is a return type that makes “not found” explicit and forces the caller to choose orElse, orElseThrow, or map.

Do not use it as a field, a JPA attribute, a DTO JSON property, or a method parameter. Do not call get() without a check. Do not use Optional to wrap collections — return an empty list.

In Spring Data, Optional<Order> findById is the right shape. In REST, “not found” becomes 404 via an exception, not an empty optional leaked to JSON.

Follow-ups

  • orElse vs orElseGet?
  • Why is Optional not Serializable in a useful way for JPA?

Trap: optional.get() everywhere, or Optional of null.

Memory sentence: Optional is for return values; empty collections stay collections.

Musterantwort

Optional ist ein Rückgabetyp, der „nicht gefunden“ explizit macht und den Caller zwingt, orElse, orElseThrow oder map zu wählen.

Nicht als Feld nutzen, nicht als JPA-Attribut, nicht als DTO-JSON-Property, nicht als Methodenparameter. Nicht get() ohne Check. Nicht Optional um Collections wickeln — eine leere Liste zurückgeben.

In Spring Data ist Optional<Order> findById die richtige Form. In REST wird „nicht gefunden“ über eine Exception zu 404, nicht als leeres Optional, das ins JSON leakt.

Nachfragen

  • orElse vs orElseGet?
  • Warum ist Optional für JPA praktisch nicht Serializable?

Falle: überall optional.get(), oder Optional von null.

Merksatz: Optional ist für Rückgabewerte; leere Collections bleiben Collections.

11. Records vs JavaBeans vs Lombok?

Deutsch

Records vs JavaBeans vs Lombok?

Level: Mid · Listen for: shallow immutability, accessors, JPA caveat

Niveau: Mid · Darauf hören sie: shallow Immutability, Accessors, JPA-Haken

Model answer

A record is a transparent, shallow-immutable data carrier: final fields, constructor, accessors, equals/hashCode/toString. Use it for DTOs, value objects, and config projections.

JavaBeans (getters/setters, no-arg constructor) exist because frameworks like JPA and Jackson historically need a mutable, constructible shape. Entities stay classes, not records, in most current JPA mappings.

Lombok generates boilerplate. It is fine if the team agrees, but it hides the real code and can surprise on equals for JPA entities (@Data on an entity is a classic bug).

Follow-ups

  • Why is @Data on a JPA entity dangerous?
  • Can a record be an @Entity?

Trap: using @Data (mutable + equals on all fields) for Hibernate entities.

Memory sentence: Records for values and DTOs; entities stay mutable classes with identity.

Musterantwort

Ein Record ist ein transparenter, shallow-immutable Datencontainer: final Fields, Konstruktor, Accessors, equals/hashCode/toString. Nutze ihn für DTOs, Value Objects und Config-Projektionen.

JavaBeans (Getter/Setter, No-Arg-Konstruktor) gibt es, weil Frameworks wie JPA und Jackson historisch eine mutable, konstruierbare Form brauchen. Entities bleiben in den meisten aktuellen JPA-Mappings Klassen, keine Records.

Lombok generiert Boilerplate. Das ist okay, wenn das Team mitzieht — aber es versteckt den echten Code und überrascht bei equals auf JPA-Entities (@Data auf einer Entity ist ein Klassiker).

Nachfragen

  • Warum ist @Data auf einer JPA-Entity gefährlich?
  • Kann ein Record ein @Entity sein?

Falle: @Data (mutable + equals auf allen Feldern) für Hibernate-Entities.

Merksatz: Records für Werte und DTOs; Entities bleiben mutable Klassen mit Identity.

12. Composition vs inheritance?

Deutsch

Composition vs Inheritance?

Level: Mid · Listen for: is-a vs has-a; fragile base class

Niveau: Mid · Darauf hören sie: is-a vs has-a; fragile base class

Model answer

Inheritance is for a true is-a relationship with polymorphic behavior. Composition is has-a: you hold a collaborator and delegate.

Inheritance leaks: subclasses depend on protected internals, and a change in the base class breaks them (fragile base class). In Spring, you also inherit all the beans’ AOP surprises.

Default: compose. Inherit only when you are modeling a stable taxonomy and you need runtime polymorphism.

Follow-ups

  • Why is extending ArrayList usually wrong?
  • How does this show up in Spring (extends a service vs injecting it)?

Trap: deep class hierarchies “for reuse”.

Memory sentence: Reuse through composition; inheritance is for polymorphism, not convenience.

Musterantwort

Inheritance ist für eine echte is-a-Beziehung mit polymorphem Verhalten. Composition ist has-a: du hältst einen Collaborator und delegierst.

Inheritance leakt: Subclasses hängen an protected Internals, und eine Änderung in der Basisklasse bricht sie (fragile base class). In Spring erbst du außerdem alle AOP-Überraschungen der Beans.

Default: komponieren. Erben nur, wenn du eine stabile Taxonomie modellierst und Runtime-Polymorphismus brauchst.

Nachfragen

  • Warum ist ArrayList zu erweitern meist falsch?
  • Wie zeigt sich das in Spring (extends auf einem Service vs injizieren)?

Falle: tiefe Klassenhierarchien „für Wiederverwendung“.

Merksatz: Wiederverwendung über Composition; Inheritance ist für Polymorphismus, nicht für Bequemlichkeit.

13. Comparable vs Comparator?

Deutsch

Comparable vs Comparator?

Level: Junior · Listen for: natural order vs external strategies

Niveau: Junior · Darauf hören sie: natürliche Ordnung vs externe Strategien

Model answer

Comparable.compareTo is the type’s natural order (String, Integer). A class has one.

Comparator is an external strategy: you can sort the same objects by date, then by name, without changing the class. Use Comparator.comparing(...).thenComparing(...).

compareTo must be consistent with equals if the type is used in TreeSet/TreeMap, or you get “missing” elements that compare equal but are not equals.

Follow-ups

  • What does a compareTo that returns 0 for unequal objects do in a TreeSet?
  • Why should compareTo throw NullPointerException on null?

Trap: using TreeSet with a comparator that disagrees with equals.

Memory sentence: Comparable is the natural order; Comparator is a plug-in order.

Musterantwort

Comparable.compareTo ist die natürliche Ordnung des Typs (String, Integer). Eine Klasse hat eine.

Comparator ist eine externe Strategie: dieselben Objekte nach Datum, dann nach Name sortieren, ohne die Klasse zu ändern. Nutze Comparator.comparing(...).thenComparing(...).

compareTo muss zu equals konsistent sein, wenn der Typ in TreeSet/TreeMap landet — sonst bekommst du „fehlende“ Elemente, die gleich vergleichen, aber nicht equals sind.

Nachfragen

  • Was macht ein compareTo, das für ungleiche Objekte 0 zurückgibt, in einem TreeSet?
  • Warum soll compareTo bei null eine NullPointerException werfen?

Falle: TreeSet mit einem Comparator, der mit equals nicht übereinstimmt.

Merksatz: Comparable ist die natürliche Ordnung; Comparator ist eine einsteckbare Ordnung.

14. What does final mean on a class, method, and variable?

Deutsch

Was bedeutet final an Klasse, Methode und Variable?

Level: Junior · Listen for: three different meanings; not “immutable”

Niveau: Junior · Darauf hören sie: drei verschiedene Bedeutungen; nicht „immutable“

Model answer
  • Class final: cannot be subclassed (String).
  • Method final: cannot be overridden.
  • Variable final: the reference or primitive cannot be reassigned after initialization. The object can still be mutated.

Local final (or effectively final) is required for use in lambdas.

Follow-ups

  • Effectively final vs final?
  • Why does Spring sometimes need non-final classes for CGLIB proxies?

Trap:final means immutable.”

Memory sentence: final freezes the reference or the hierarchy, not the object graph.

Musterantwort

  • Klasse final: kann nicht erweitert werden (String).
  • Methode final: kein Override.
  • Variable final: die Referenz oder der primitive Wert kann nach der Initialisierung nicht neu zugewiesen werden. Das Objekt selbst darf trotzdem mutieren.

Lokales final (oder effectively final) brauchst du für Lambdas.

Nachfragen

  • Effectively final vs final?
  • Warum braucht Spring manchmal nicht-finale Klassen für CGLIB-Proxies?

Falle:final heißt immutable.“

Merksatz: final friert die Referenz oder die Hierarchie ein, nicht den Objektgraphen.

15. == vs equals for wrappers and interned integers?

Deutsch

== vs equals bei Wrappers und interned Integers?

Level: Mid · Listen for: Integer cache −128..127

Niveau: Mid · Darauf hören sie: Integer-Cache −128..127

Model answer

== on objects is identity. equals is value, if implemented.

For Integer, autoboxing uses a cache for −128 to 127. Integer a = 127; Integer b = 127; a == b may be true; 128 may be false. Never use == for wrappers.

Same family of bugs: Boolean, interned strings vs new String("x").

Follow-ups

  • What does new Integer(1) do compared to Integer.valueOf(1)? (new Integer is deprecated)
  • Why is == OK for enums?

Trap: “it worked on my machine” because the values were in the cache.

Memory sentence: Compare wrappers and strings with equals; == is identity (and enum identity).

Musterantwort

== auf Objekten ist Identität. equals ist der Wert, falls implementiert.

Bei Integer nutzt Autoboxing einen Cache für −128 bis 127. Integer a = 127; Integer b = 127; a == b kann true sein; bei 128 kann es false sein. Nie == für Wrappers.

Dieselbe Bug-Familie: Boolean, interned Strings vs new String("x").

Nachfragen

  • Was macht new Integer(1) im Vergleich zu Integer.valueOf(1)? (new Integer ist deprecated)
  • Warum ist == bei Enums okay?

Falle: „Bei mir hat's funktioniert“, weil die Werte im Cache lagen.

Merksatz: Wrapper und Strings mit equals vergleichen; == ist Identität (und Enum-Identität).

16. What is a memory leak in Java if you have a GC?

Deutsch

Was ist ein Memory Leak in Java, obwohl es einen GC gibt?

Level: Mid · Listen for: reachable but unused objects

Niveau: Mid · Darauf hören sie: erreichbare, aber ungenutzte Objekte

Model answer

The GC frees objects that are unreachable. A Java leak is an object you still reference but no longer need: static collections, uncleared ThreadLocals, listeners not deregistered, caches without eviction, unbounded queues.

Symptoms: growing heap, frequent GC, then OutOfMemoryError. Tools: heap dump, allocation flame graphs, not “add more RAM” as the first fix.

In Spring: static maps, prototype beans holding request data, ThreadLocal in filters without remove() in finally.

Follow-ups

  • How can a HashMap with a custom key leak if equals/hashCode change?
  • How do you find a leak in production?

Trap: “Java cannot leak because of GC.”

Memory sentence: GC collects the unreachable; leaks are reachable leftovers.

Musterantwort

Der GC räumt Objekte ab, die unreachable sind. Ein Java-Leak ist ein Objekt, das du noch referenzierst, aber nicht mehr brauchst: statische Collections, nicht geräumte ThreadLocals, Listener, die nicht abgemeldet wurden, Caches ohne Eviction, unbeschränkte Queues.

Symptome: wachsender Heap, häufiger GC, dann OutOfMemoryError. Tools: Heap Dump, Allocation-Flamegraphs — nicht „mehr RAM“ als ersten Fix.

In Spring: statische Maps, Prototype-Beans, die Request-Daten halten, ThreadLocal in Filtern ohne remove() in finally.

Nachfragen

  • Wie kann eine HashMap mit einem Custom-Key leaken, wenn sich equals/hashCode ändern?
  • Wie findest du ein Leak in Produktion?

Falle: „Java kann nicht leaken, es gibt GC.“

Merksatz: Der GC sammelt Unreachable; Leaks sind erreichbare Reste.