Oracle Java Foundations common mistakes
Oracle Java Foundations · Understand the traps and how to avoid them.
Declares the entry point as `public void main(String[] args)` or `static void main(String[] args)` and expects the JVM to launch the class.
The candidate remembers the words 'main' and 'String args' but not that every modifier and the array parameter type are mandatory. The compiler accepts the method as an ordinary method, so the problem only surfaces at run time as 'no main method found'.
What to do instead
Memorise the exact signature public static void main(String[] args): public and static are both required, the return type must be void, and the parameter must be String[] (or String...). Verify by executing the class, not just compiling it.
Writes `float ratio = 3.5;` and expects it to compile because 3.5 obviously fits inside a float.
A floating-point literal with no suffix is a double, and double-to-float is a narrowing conversion, not a widening one. Candidates over-generalise from the integer rule that a small literal fits a small type.
What to do instead
Add the suffix (3.5f) or cast ((float) 3.5). Remember double is the default type for floating-point literals and for any expression that mixes in a double.
Writes `byte b = 10; b = b + 1;` and expects the second line to compile.
Binary numeric promotion widens b and 1 to int, so b + 1 is an int and cannot be assigned back to a byte. The legal first line (byte b = 10;) is a constant-narrowing special case and misleads candidates into thinking byte arithmetic stays byte.
What to do instead
Use the compound form b += 1, which carries an implicit cast, or write b = (byte)(b + 1);. Note that constant narrowing only applies when the right-hand side is a compile-time constant that fits.
Predicts that only the matching case body executes in a switch and ignores the statements that follow it.
switch is fall-through by design, but candidates read it like an if/else chain and stop at the end of the matched block.
What to do instead
Trace every case from the match downward and stop only at break, return, throw, or the closing brace. Place break deliberately and re-check any case without one.
Calls `arr.length()` on an array, or calls `s.length` on a String, mixing up field and method forms.
length is a public final field on arrays but a method on String and StringBuilder, and size() on collections. Habit from String use bleeds into array code.
What to do instead
Keep the table straight: array -> arr.length (field, no parentheses); String -> s.length(); StringBuilder -> sb.length(); List/Set/Map -> size().
Assumes a plain `break` inside a nested loop exits both loops and continues with the statement after the outer loop.
break is described casually as 'exit the loop', so candidates picture the whole nest instead of the innermost enclosing loop or switch.
What to do instead
Use a labelled break (outer: for(...) { ... break outer; }) when you need to leave several levels; otherwise remember unlabelled break/continue act only on the innermost loop or switch that encloses them.
Tries to overload a method by changing only its return type, e.g. `int get()` and `String get()` in the same class.
The return type feels like part of the method's identity, so candidates are surprised by the 'method is already defined' error.
What to do instead
A signature is the method name plus the parameter types and their order, nothing else. Overload by varying the parameter list (count, types, order) or rename the method; return type alone never distinguishes two methods.
Assumes constructors are inherited, so a subclass can be created with the parent's constructor arguments without declaring its own constructor.
Constructors look like members, and other members are inherited, so candidates carry the rule across. In fact constructors are never inherited, and an implicit super() call fails when the parent has no no-argument constructor.
What to do instead
Treat constructors as outside inheritance: declare the subclass constructor you need and call super(...) explicitly when the parent lacks a no-arg constructor. Check every subclass whose parent defines only argument-taking constructors.
Orders catch blocks with the supertype first, e.g. `catch (Exception e)` before `catch (IOException e)`, and expects it to compile and run.
It reads like a sensible most-general fallback, but the compiler rejects the later, more specific handler as unreachable because the earlier one already covers it.
What to do instead
Order handlers from most specific to most general, ending with Exception (or Throwable) if needed, and use multi-catch (catch (IOException | SQLException e)) when several types share one handler.
Compares two Strings with == and treats the result as value equality, especially when one side comes from `new String(...)`.
== compares references, and because literals are interned some comparisons accidentally evaluate true, which reinforces the wrong mental model.
What to do instead
Use equals (or Objects.equals for null safety) for value comparison; use == on references only when identity is genuinely what you mean. Test the case where one operand is constructed with new.