QA Interview Hub · Knowledge base · Quizzes

Java basics

The language for tests

Types, String and the difference between == and equals

Java has two kinds of types: primitives (int, long, double, boolean) and reference types (classes, arrays, String, the wrappers Integer, Boolean). A primitive holds a value, a reference holds the address of an object, so it can be null.

== versus equals. For primitives == compares values. For objects == compares references (is it the same object) while equals compares content, if the class overrides it.

String a = "qa";
String b = new String("qa");
a == b;        // false: different objects
a.equals(b);   // true: same text

String literals go into a pool, so "qa" == "qa" is always true, but strings built at run time (from an API response, by concatenating variables, with new String) are separate objects, so you cannot rely on ==. In tests, strings are always compared with equals (or an assertion library), and with Objects.equals(a, b) when null is possible.

Pitfalls for an automation engineer:

  • Wrappers: Integer values from −128 to 127 are cached, so == "works" for small numbers and breaks for large ones. Compare with equals or unbox to int.
  • Unboxing null into a primitive throws NullPointerException: int id = response.getId(); when the field is an Integer holding null.
  • Money and exact decimals: BigDecimal built from a string (new BigDecimal("0.10")). double gives 0.1 + 0.2 != 0.3. Compare with compareTo: equals treats 2.0 and 2.00 as different.

Modern Java for tests: var, enum, record and text blocks

The current Java LTS is 25 (earlier 21, 17, 11). New automation projects should start on an LTS and use the features that remove boilerplate.

  • enum — a fixed set of values: browsers, environments, roles. A typo in a name shows up at compile time, and a switch over an enum lists the options explicitly.
    enum Browser { CHROME, FIREFOX, EDGE }
    Browser b = Browser.valueOf(System.getProperty("browser", "chrome").toUpperCase());
    valueOf throws IllegalArgumentException for an unknown name, a fast and clear failure at start-up instead of odd behaviour in the middle of a run.
  • record (Java 16) — an immutable data carrier: the compiler adds a constructor, accessors such as email(), equals, hashCode and toString.
    record Credentials(String email, String password) {}
    Handy for test data and parameters. A record cannot be extended and cannot change after creation; Jackson (2.12+) can read and write records.
  • var (Java 10) — local variable type inference: var users = new ArrayList<User>();. The type stays static; var is not for fields and parameters. Do not overuse it when the type is not obvious from the right-hand side.
  • Text blocks (Java 15) — multi-line strings in triple quotes, convenient for JSON bodies and SQL:
    String body = """
        {"email": "a@example.com", "role": "admin"}
        """;
  • Pattern matching for instanceof (o instanceof User u) and switch expressions shorten type checks.

All of this is only syntax: it does not change test speed, but it makes test-data code shorter and safer.