Skip to content

Programming Basics — Java vs Python vs JavaScript

Side-by-side fundamentals refresh for SDETs using all three languages. Java = Rest Assured automation • Python = data validation in Jupyter • JavaScript/TypeScript = Playwright

Every concept has: what it is, why it exists, example in each language, and common pitfalls.


QUICK LANGUAGE OVERVIEW

Feature Java Python JavaScript
Typing Static (declared) Dynamic (inferred) Dynamic (inferred)
Type checking Compile-time Runtime Runtime
Execution Compiled to bytecode → JVM Interpreted Interpreted (V8 engine)
Memory Garbage collected Garbage collected Garbage collected
Paradigm OOP-first Multi-paradigm Multi-paradigm
Indentation Curly braces {} Significant whitespace Curly braces {}
Statement end Semicolon ; required Newline (no ;) Semicolon optional
Main use in QA API automation (Rest Assured), Selenium Data validation, scripts Playwright, Cypress

Memory hook

  • Java = "Strict and structured" — like a formal office. Verbose but predictable.
  • Python = "Clean and concise" — like a notebook. Reads like English.
  • JavaScript = "Flexible and fast" — like a startup. Quirky but powerful.

1. HELLO WORLD — your first program

Java

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
Why so verbose? - public class Hello — every Java file must contain a class - public static void main(String[] args) — JVM looks for this exact method as the entry point - static = no need to create an object - void = returns nothing - String[] args = command-line arguments - System.out.println = standard output stream

Python

print("Hello, World!")
Why simple? Python is designed for readability. No class wrapper required. The interpreter runs from top to bottom.

JavaScript

console.log("Hello, World!");
Why console.log? Originally JS ran in browsers — console was the browser dev tools console. Node.js kept the same API for compatibility.


2. VARIABLES & DATA TYPES

Why variables exist

To store data for later use. Each language has primitive types (raw values) and reference types (objects).

Java — Static typing

int age = 25;           // 32-bit integer
long bigNum = 1000000L; // 64-bit integer, L suffix
double price = 99.99;   // 64-bit floating point
boolean isActive = true;
char letter = 'A';      // single char, single quotes
String name = "Rohan";  // String is an object, not primitive
final int MAX = 100;    // final = constant, cannot be reassigned
Why type declaration? Compiler catches type errors before running. Trade-off: more verbose, fewer runtime surprises.

Python — Dynamic typing

age = 25              # int
price = 99.99         # float
is_active = True      # bool (capital T/F)
name = "Rohan"        # str
nothing = None        # None (Python's null)
MAX = 100             # convention: uppercase = constant (not enforced)
Why no type? Python infers it from the value. Same variable can hold different types over time:
x = 5         # int now
x = "hello"   # str now — totally legal

JavaScript — Dynamic typing with 3 declarations

let age = 25;            // block-scoped, reassignable
const price = 99.99;     // block-scoped, cannot reassign
var name = "Rohan";      // function-scoped (old, avoid in new code)

let active = true;
let nothing = null;      // explicit absence
let notSet;              // undefined — never assigned
Why three? var was original (1995). let and const came in ES6 (2015) to fix scoping bugs. Rule of thumb: Use const by default, let when you need to reassign, never var.

Pitfall: Primitive vs Object types

Type Java Python JavaScript
Integer int (primitive), Integer (object) int (everything is object) number (no distinction)
Decimal double, float float number
Text String (object) str string
True/False boolean bool boolean
Nothing null None null and undefined

3. MUTABLE vs IMMUTABLE — Critical concept

What is mutability?

  • Mutable = can be changed after creation
  • Immutable = cannot be changed; modification creates a new object

Why does it matter?

  1. Performance — immutable objects can be safely shared between threads
  2. Bugs — passing mutable objects to functions can cause unexpected side effects
  3. HashMap keys — keys must be immutable (otherwise lookups break)

Java

// Immutable
String s = "Hello";
s.concat(" World");      // returns NEW string, s is unchanged
System.out.println(s);   // "Hello"
s = s.concat(" World");  // reassignment needed to see change

// Mutable
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");     // modifies sb in place
System.out.println(sb);  // "Hello World"

// Immutable: String, Integer, all primitives wrapper classes
// Mutable: StringBuilder, ArrayList, HashMap

Python

# Immutable: str, int, float, tuple, frozenset
s = "Hello"
s.upper()          # returns NEW string "HELLO", s unchanged
print(s)           # "Hello"
s = s.upper()      # reassign to see change

# Mutable: list, dict, set
lst = [1, 2, 3]
lst.append(4)      # modifies in place
print(lst)         # [1, 2, 3, 4]

# Tuple = immutable list
t = (1, 2, 3)
# t[0] = 5         # ERROR: tuples don't support assignment

JavaScript

// Primitives (immutable): string, number, boolean, null, undefined, symbol
let s = "Hello";
s.toUpperCase();    // returns new string "HELLO", s unchanged
s = s.toUpperCase();

// Objects (mutable): object, array, function
const arr = [1, 2, 3];
arr.push(4);        // modifies in place
// const protects REFERENCE, not contents!
// arr = [];        // ERROR
arr.length = 0;     // OK — modifies contents

Pitfall: Passing mutable objects

def add_item(my_list):
    my_list.append("oops")   # modifies caller's list!

items = [1, 2, 3]
add_item(items)
print(items)  # [1, 2, 3, 'oops'] — caller surprised!
Fix: Make a copy first: add_item(items.copy())


4. STRINGS — Text handling

Java

String name = "Rohan";
String greeting = "Hello, " + name + "!";          // concatenation
String formatted = String.format("Age: %d", 25);   // formatted
String template = "Name: %s, Age: %d".formatted("Rohan", 25);

// Common methods
name.length();              // 5
name.toUpperCase();         // "ROHAN"
name.substring(0, 3);       // "Roh"
name.contains("oh");        // true
name.replace("R", "B");     // "Bohan"
name.split(",");            // splits into array
" hi ".trim();              // "hi"

// Equality — critical Java pitfall
String a = "hi";
String b = "hi";
a == b;            // true (string pool) — but DON'T rely on this
a.equals(b);       // true — ALWAYS use equals() for content check

Python

name = "Rohan"
greeting = "Hello, " + name + "!"
greeting = f"Hello, {name}!"               # f-string (preferred)
greeting = "Hello, {}!".format(name)       # older style

# Common methods
len(name)             # 5
name.upper()          # "ROHAN"
name[0:3]             # "Roh" (slicing)
"oh" in name          # True
name.replace("R", "B")
name.split(",")
"  hi  ".strip()      # "hi"

# Equality — simple in Python
a = "hi"
b = "hi"
a == b               # True — works as expected

JavaScript

const name = "Rohan";
const greeting = "Hello, " + name + "!";
const tmpl = `Hello, ${name}!`;       // template literal (preferred)

// Common methods
name.length;                // 5 (property, no parens!)
name.toUpperCase();
name.substring(0, 3);       // "Roh"
name.includes("oh");        // true
name.replace("R", "B");
name.split(",");
"  hi  ".trim();

// Equality
"hi" === "hi";    // true — use === (strict)
"hi" == "hi";     // true — but avoid == (loose, has quirks)

Pitfall: String concatenation in loops

// SLOW — creates new String each iteration
String s = "";
for (int i = 0; i < 1000; i++) s += i;

// FAST — uses mutable StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) sb.append(i);
String s = sb.toString();

5. ARRAYS / LISTS — Ordered collections

Why both? "Array" and "List"

  • Array = fixed size, contiguous memory, fast indexing
  • List = dynamic size, can grow/shrink

Java

// Array — fixed size
int[] nums = {1, 2, 3, 4, 5};
nums[0] = 10;             // mutate
int x = nums[2];          // read
nums.length;              // 5 (property)
// nums.add(6);           // ERROR: arrays can't grow

// ArrayList — dynamic size (most common)
import java.util.ArrayList;
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.get(0);              // 1
list.set(0, 10);          // update
list.remove(0);           // delete by index
list.size();              // method
list.contains(2);

Python

# Python doesn't have arrays in core — uses list (dynamic)
nums = [1, 2, 3, 4, 5]
nums[0] = 10              # mutate
nums.append(6)            # add to end
nums.insert(0, 99)        # add at index
nums.pop()                # remove last
nums.remove(3)            # remove by value
len(nums)                 # function, not method
3 in nums                 # True/False

# Slicing — very Pythonic
nums[1:3]                 # elements 1 to 2 (exclusive end)
nums[::-1]                # reverse
nums[::2]                 # every 2nd element

JavaScript

// Array — dynamic by default
const nums = [1, 2, 3, 4, 5];
nums[0] = 10;             // mutate
nums.push(6);             // add to end
nums.unshift(0);          // add to start
nums.pop();               // remove last
nums.shift();             // remove first
nums.length;              // 5 (property)
nums.includes(3);

// Functional methods (very common)
nums.map(n => n * 2);             // transform
nums.filter(n => n > 2);          // keep matching
nums.reduce((a, b) => a + b);     // accumulate
nums.find(n => n > 3);            // first match
nums.some(n => n > 4);            // any match? true/false
nums.every(n => n > 0);           // all match?

Comparison table

Operation Java Python JavaScript
Create new ArrayList<>() [] []
Add to end list.add(x) list.append(x) arr.push(x)
Remove from end list.remove(size-1) list.pop() arr.pop()
Length list.size() len(list) arr.length
Contains list.contains(x) x in list arr.includes(x)
Copy new ArrayList<>(list) list.copy() or list[:] [...arr]

6. MAPS / DICTIONARIES / OBJECTS — Key-value pairs

Why?

For lookup by name instead of index. O(1) average lookup time.

Java — HashMap

import java.util.HashMap;
HashMap<String, Integer> ages = new HashMap<>();
ages.put("Rohan", 28);
ages.put("Asha", 25);
ages.get("Rohan");           // 28
ages.containsKey("Asha");    // true
ages.remove("Rohan");
ages.size();

// Iterate
for (String name : ages.keySet()) { ... }
for (var entry : ages.entrySet()) {
    System.out.println(entry.getKey() + "=" + entry.getValue());
}

Python — Dictionary

ages = {"Rohan": 28, "Asha": 25}
ages["Rohan"]            # 28 — KeyError if missing
ages.get("Rohan", 0)     # 28 — returns 0 if missing (safe)
ages["Bob"] = 30         # add or update
"Asha" in ages           # True
del ages["Rohan"]
len(ages)

# Iterate
for name in ages: ...
for name, age in ages.items(): ...

JavaScript — Object & Map

// Object — keys are always strings
const ages = { Rohan: 28, Asha: 25 };
ages.Rohan;             // 28 — dot notation
ages["Rohan"];          // 28 — bracket notation
ages.Bob = 30;          // add
"Asha" in ages;         // true
delete ages.Rohan;
Object.keys(ages);      // ["Asha", "Bob"]
Object.values(ages);
Object.entries(ages);   // [["Asha", 25], ["Bob", 30]]

// Map — modern alternative, keys can be ANY type
const m = new Map();
m.set("Rohan", 28);
m.get("Rohan");
m.has("Rohan");
m.delete("Rohan");
m.size;

When to use Object vs Map in JS? - Object: simple records, JSON, default choice - Map: keys are not strings, need to preserve insertion order strictly, frequently add/remove


7. SETS — Unique values

Why?

  • Remove duplicates
  • Fast "is this in the collection?" lookup (O(1) avg)

Java

import java.util.HashSet;
HashSet<String> tags = new HashSet<>();
tags.add("java");
tags.add("java");        // duplicate ignored
tags.contains("java");   // true
tags.remove("java");
tags.size();

Python

tags = {"java", "python", "java"}   # {"java", "python"}
tags.add("javascript")
"java" in tags
tags.remove("java")
len(tags)

# Common set operations
a = {1, 2, 3}
b = {2, 3, 4}
a | b                # union: {1,2,3,4}
a & b                # intersection: {2,3}
a - b                # difference: {1}

JavaScript

const tags = new Set();
tags.add("js");
tags.add("js");          // duplicate ignored
tags.has("js");          // true
tags.delete("js");
tags.size;

// Common trick: dedupe an array
const unique = [...new Set([1, 1, 2, 3, 3])];   // [1, 2, 3]

8. CONTROL FLOW — if / else / switch

Java

if (age >= 18) {
    System.out.println("Adult");
} else if (age >= 13) {
    System.out.println("Teen");
} else {
    System.out.println("Child");
}

// Switch (modern Java 14+)
String role = switch (level) {
    case 1, 2 -> "Junior";
    case 3, 4 -> "Mid";
    case 5    -> "Senior";
    default   -> "Unknown";
};

// Ternary
String status = age >= 18 ? "Adult" : "Minor";

Python — no parentheses, uses indentation

if age >= 18:
    print("Adult")
elif age >= 13:
    print("Teen")
else:
    print("Child")

# Ternary (different syntax!)
status = "Adult" if age >= 18 else "Minor"

# Match (Python 3.10+) — like switch
match status_code:
    case 200: print("OK")
    case 404: print("Not found")
    case 500 | 502 | 503: print("Server error")
    case _: print("Unknown")          # default

JavaScript

if (age >= 18) {
    console.log("Adult");
} else if (age >= 13) {
    console.log("Teen");
} else {
    console.log("Child");
}

// Switch
switch (level) {
    case 1:
    case 2:
        role = "Junior";
        break;            // CRITICAL: prevents fall-through
    case 3:
        role = "Mid";
        break;
    default:
        role = "Unknown";
}

// Ternary
const status = age >= 18 ? "Adult" : "Minor";

Pitfall: Truthy vs Falsy

Language Falsy values
Java false only (if(0) is compile error — must be boolean)
Python False, 0, 0.0, "", [], {}, None
JavaScript false, 0, "", null, undefined, NaN

9. LOOPS — for / while

Java

// Classic for
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// For-each (enhanced for)
int[] nums = {1, 2, 3};
for (int n : nums) {
    System.out.println(n);
}

// While
int i = 0;
while (i < 10) {
    i++;
}

// Do-while (runs at least once)
do {
    i++;
} while (i < 10);

// Break + continue
for (int n : nums) {
    if (n == 2) continue;   // skip this iteration
    if (n == 5) break;      // exit loop
}

Python

# For (always iterates over a collection)
for i in range(10):           # 0 to 9
    print(i)

for i in range(1, 10, 2):     # start, stop, step → 1,3,5,7,9
    print(i)

# For-each (most common)
for n in nums:
    print(n)

# With index
for i, n in enumerate(nums):
    print(i, n)

# While
i = 0
while i < 10:
    i += 1

# No do-while in Python

JavaScript

// Classic for
for (let i = 0; i < 10; i++) { ... }

// For-of (values)
for (const n of nums) { ... }

// For-in (keys/indices — be careful with arrays)
for (const key in obj) { ... }

// Functional alternatives
nums.forEach(n => console.log(n));   // simple iteration
nums.map(n => n * 2);                // transform

// While
let i = 0;
while (i < 10) { i++; }

// Do-while
do { i++; } while (i < 10);

Memory hook

  • Java/JS — three loop styles (classic for, for-each, while)
  • Python — for is always "for-each", use range() to count

10. FUNCTIONS / METHODS

Java

public static int add(int a, int b) {
    return a + b;
}

// In a class (typical)
public class Calculator {
    public int multiply(int a, int b) {
        return a * b;
    }
}

// Method overloading (same name, different params)
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; }

// Varargs (variable arguments)
public int sum(int... nums) {
    int total = 0;
    for (int n : nums) total += n;
    return total;
}
sum(1, 2, 3, 4);   // 10

// Lambda (Java 8+)
Function<Integer, Integer> square = n -> n * n;
square.apply(5);   // 25

Python

def add(a, b):
    return a + b

# Default values
def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

# Keyword arguments
greet(name="Rohan", greeting="Hi")

# *args (variable positional) + **kwargs (variable keyword)
def example(*args, **kwargs):
    print(args)      # tuple
    print(kwargs)    # dict

example(1, 2, 3, name="Rohan", age=28)

# Lambda
square = lambda n: n * n
square(5)   # 25

# Type hints (optional, but recommended)
def add(a: int, b: int) -> int:
    return a + b

JavaScript

// Function declaration
function add(a, b) {
    return a + b;
}

// Function expression
const add = function(a, b) { return a + b; };

// Arrow function (modern preferred)
const add = (a, b) => a + b;
const square = n => n * n;             // single param, no parens needed
const greet = () => "Hello";           // no params

// Default values
function greet(name, greeting = "Hello") {
    return `${greeting}, ${name}!`;
}

// Rest parameters (variable args)
function sum(...nums) {
    return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4);   // 10

// Destructuring parameters
function createUser({ name, age, email }) {
    return { name, age, email };
}
createUser({ name: "Rohan", age: 28, email: "r@x.com" });

Arrow function vs regular function (JS gotcha)

  • Arrow functions don't have their own this — they inherit from surrounding scope
  • Critical when using in callbacks, event handlers, class methods

11. CLASSES & OBJECTS — OOP basics

Java — class-based, strict

public class User {
    // Fields (state)
    private String name;
    private int age;

    // Constructor
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Methods (behavior)
    public String greet() {
        return "Hello, I'm " + name;
    }

    // Getter / Setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

// Usage
User u = new User("Rohan", 28);
u.greet();

Python — class-based, flexible

class User:
    # Constructor
    def __init__(self, name, age):
        self.name = name        # 'self' refers to current instance
        self.age = age

    # Method (always takes 'self' as first param)
    def greet(self):
        return f"Hello, I'm {self.name}"

# Usage
u = User("Rohan", 28)
u.greet()

JavaScript — class syntax (ES6+) on top of prototypes

class User {
    // Constructor
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    // Method
    greet() {
        return `Hello, I'm ${this.name}`;
    }

    // Static method (called on class, not instance)
    static fromString(str) {
        const [name, age] = str.split(",");
        return new User(name, parseInt(age));
    }
}

// Usage
const u = new User("Rohan", 28);
u.greet();
User.fromString("Rohan,28");

12. INHERITANCE & POLYMORPHISM

Why inheritance?

  • Reuse code — child class gets parent's properties
  • Polymorphism — treat different types uniformly

Java

public class Animal {
    public void speak() { System.out.println("Some sound"); }
}

public class Dog extends Animal {
    @Override
    public void speak() { System.out.println("Woof!"); }
}

// Polymorphism
Animal a = new Dog();      // parent reference, child object
a.speak();                 // "Woof!" — runtime dispatch

Python

class Animal:
    def speak(self):
        print("Some sound")

class Dog(Animal):
    def speak(self):                  # override
        print("Woof!")

# Multiple inheritance (allowed)
class A: pass
class B: pass
class C(A, B): pass

# super() — call parent method
class Dog(Animal):
    def speak(self):
        super().speak()    # "Some sound"
        print("Woof!")

JavaScript

class Animal {
    speak() { console.log("Some sound"); }
}

class Dog extends Animal {
    speak() {
        super.speak();             // call parent
        console.log("Woof!");
    }
}

13. INTERFACES / ABSTRACT CLASSES

Java — interface = contract (no implementation traditionally)

public interface Vehicle {
    void start();                    // abstract by default
    void stop();
    default void honk() {            // default method (Java 8+)
        System.out.println("Beep!");
    }
}

public class Car implements Vehicle {
    public void start() { System.out.println("Vroom"); }
    public void stop()  { System.out.println("Brake"); }
}

Python — abstract base class (use abc module)

from abc import ABC, abstractmethod

class Vehicle(ABC):
    @abstractmethod
    def start(self): pass

    @abstractmethod
    def stop(self): pass

class Car(Vehicle):
    def start(self): print("Vroom")
    def stop(self): print("Brake")

JavaScript — no native interfaces (use TypeScript)

// TypeScript
interface Vehicle {
    start(): void;
    stop(): void;
}

class Car implements Vehicle {
    start() { console.log("Vroom"); }
    stop() { console.log("Brake"); }
}

14. EXCEPTION HANDLING — try/catch/finally

Java — checked exceptions (must declare or handle)

try {
    FileReader f = new FileReader("file.txt");
} catch (FileNotFoundException e) {
    System.out.println("File missing: " + e.getMessage());
} catch (Exception e) {
    System.out.println("Other error: " + e.getMessage());
} finally {
    System.out.println("Always runs");
}

// Throw custom exception
public class MyException extends RuntimeException {
    public MyException(String msg) { super(msg); }
}
throw new MyException("Bad thing");

// Try-with-resources (auto-close)
try (FileReader f = new FileReader("f.txt")) {
    // f is auto-closed even if exception
}

Python

try:
    f = open("file.txt")
except FileNotFoundError as e:
    print(f"Missing: {e}")
except Exception as e:
    print(f"Other: {e}")
else:
    print("No exception")     # runs if no exception
finally:
    print("Always")

# Raise
raise ValueError("Bad input")

# Custom exception
class MyError(Exception): pass
raise MyError("Bad")

# Context manager (auto-close)
with open("f.txt") as f:
    data = f.read()

JavaScript

try {
    JSON.parse(invalidString);
} catch (e) {
    console.error("Parse error:", e.message);
} finally {
    console.log("Always");
}

// Throw
throw new Error("Bad thing");

// Custom
class MyError extends Error {
    constructor(msg) {
        super(msg);
        this.name = "MyError";
    }
}

15. ASYNC / CONCURRENCY

Why async?

For non-blocking I/O — network calls, file reads, DB queries. Lets the program do other work while waiting.

Java — Threads, CompletableFuture

// Thread
Thread t = new Thread(() -> System.out.println("Hi"));
t.start();
t.join();   // wait for completion

// CompletableFuture (modern async)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    return "result";
});
future.thenAccept(result -> System.out.println(result));

Python — asyncio

import asyncio

async def fetch_data():
    await asyncio.sleep(1)        # non-blocking wait
    return "data"

async def main():
    result = await fetch_data()
    print(result)

asyncio.run(main())

JavaScript — Promise + async/await

// Promise
fetch("/api/data")
    .then(res => res.json())
    .then(data => console.log(data))
    .catch(err => console.error(err));

// async/await (much cleaner)
async function loadData() {
    try {
        const res = await fetch("/api/data");
        const data = await res.json();
        console.log(data);
    } catch (err) {
        console.error(err);
    }
}

// Parallel
const [a, b] = await Promise.all([fetchA(), fetchB()]);

Pitfall: forgetting await

// WRONG — userId is a Promise, not the value
const userId = createUser();

// RIGHT
const userId = await createUser();

16. MODULES / IMPORTS

Java — packages

// Define
package com.questt.utils;
public class StringUtils { ... }

// Import
import com.questt.utils.StringUtils;
import java.util.*;          // wildcard
import static java.lang.Math.PI;   // static import

Python — modules

# math_utils.py
def add(a, b): return a + b

# main.py
import math_utils
math_utils.add(1, 2)

from math_utils import add
add(1, 2)

from math_utils import add as plus     # alias

import math
math.pi

JavaScript — ES Modules

// utils.js
export function add(a, b) { return a + b; }
export const PI = 3.14;
export default function main() { ... }    // one default per file

// main.js
import { add, PI } from "./utils.js";
import main from "./utils.js";            // default import
import * as utils from "./utils.js";      // namespace

// CommonJS (older Node.js)
const { add } = require("./utils");
module.exports = { add };

17. NULL / NONE / UNDEFINED

Java

String name = null;
if (name == null) ...
if (name != null && name.length() > 0) ...    // null check first!

// Optional (Java 8+) — explicit "maybe value"
Optional<String> maybe = Optional.of("hi");
maybe.ifPresent(System.out::println);
maybe.orElse("default");

// NullPointerException — the #1 Java bug
String s = null;
s.length();    // NPE!

Python

name = None
if name is None: ...         # use 'is None', not '== None'
if name is not None: ...

# AttributeError if you call method on None
name.upper()   # AttributeError

JavaScript — has TWO!

let a;            // undefined (never assigned)
let b = null;     // null (intentionally empty)

// Optional chaining (?.) — safe nested access
user?.address?.city;       // undefined if any step is null/undefined

// Nullish coalescing (??)
const name = user.name ?? "Anonymous";   // use right if left is null/undefined

// Common mistake
const score = 0;
const display = score || "N/A";    // "N/A" — but 0 is valid!
const display = score ?? "N/A";    // 0 — correct

18. TYPE CONVERSION

Java

// Implicit (widening) — safe
int i = 10;
long l = i;          // OK
double d = i;        // OK

// Explicit (narrowing) — must cast
double d = 9.99;
int i = (int) d;     // 9 (truncates)

// String <-> number
int n = Integer.parseInt("42");
String s = String.valueOf(42);
String s2 = Integer.toString(42);

Python

int("42")        # 42
str(42)          # "42"
float("3.14")    # 3.14
int("abc")       # ValueError

# Truthy/falsy
bool(0)          # False
bool("")         # False
bool([])         # False
bool("hi")       # True

JavaScript

parseInt("42");          // 42
parseFloat("3.14");      // 3.14
String(42);              // "42"
Number("42");            // 42
Number("abc");           // NaN

// Implicit conversion gotchas
"5" + 3;          // "53" (string concat — + with string)
"5" - 3;          // 2 (numeric — - forces number)
[] + [];          // "" (empty string!)
{} + [];          // 0 (or "[object Object]" — context dependent)

19. COMMON COLLECTIONS COMPARISON

Concept Java Python JavaScript
Dynamic array ArrayList list Array
Fixed array int[], String[] (use list) (use Array)
Linked list LinkedList collections.deque (use Array)
Hash map HashMap dict Object or Map
Hash set HashSet set Set
Tree map (sorted) TreeMap sortedcontainers.SortedDict (3rd party) (none built-in)
Queue Queue, LinkedList collections.deque (use Array)
Stack Deque (preferred over Stack) list (append/pop) (use Array)
Tuple (immutable) record (Java 14+) tuple (none — use frozen array)

20. MEMORY & GARBAGE COLLECTION

All three languages use garbage collection — you don't manually free memory.

Java

  • JVM has multiple GC algorithms (G1, ZGC, Parallel)
  • Tune with flags like -Xmx2g (max heap), -XX:+UseG1GC
  • Watch out for memory leaks via static collections, listener registration

Python

  • Uses reference counting + cyclic GC
  • Objects freed when refcount hits 0
  • Use del to explicitly remove a reference (not the object)

JavaScript

  • V8 uses generational GC (young + old heap)
  • Watch for memory leaks: detached DOM nodes, forgotten event listeners, closures holding large data

21. PASS BY VALUE vs PASS BY REFERENCE

The truth (often misunderstood)

  • Java: Always pass-by-value — but for objects, the "value" is the reference
  • Python: Pass-by-object-reference — similar to Java
  • JavaScript: Same as Java/Python

What this means in practice

def change(lst):
    lst.append(99)       # MUTATES the original — both see it
    lst = [1, 2]         # REBINDS local var — caller doesn't see this

x = [10, 20]
change(x)
print(x)   # [10, 20, 99] — append was visible; reassignment was not

Same behavior in Java with objects and in JavaScript with arrays/objects.


22. NAMING CONVENTIONS

Item Java Python JavaScript
Variable camelCase snake_case camelCase
Constant UPPER_SNAKE UPPER_SNAKE UPPER_SNAKE
Class PascalCase PascalCase PascalCase
Method camelCase snake_case camelCase
File PascalCase.java snake_case.py camelCase.js or kebab-case.js
Package com.company.feature lowercase camelCase or kebab-case

23. COMMENTS & DOCSTRINGS

Java

// Single line
/* Multi-line */
/** Javadoc — used to generate API docs
 * @param name the user name
 * @return greeting
 */
public String greet(String name) { ... }

Python

# Single line — no multi-line comment syntax!

"""
Triple-quoted strings used as docstrings.
"""

def greet(name):
    """
    Return a greeting for the given name.

    Args:
        name (str): the user name
    Returns:
        str: the greeting
    """
    return f"Hello, {name}"

JavaScript

// Single line
/* Multi-line */
/**
 * JSDoc — generates docs and helps IDEs
 * @param {string} name - the user name
 * @returns {string} greeting
 */
function greet(name) { ... }

24. PACKAGING & DEPENDENCY MANAGEMENT

Language Build tool Dependency file
Java Maven, Gradle pom.xml, build.gradle
Python pip, poetry, uv requirements.txt, pyproject.toml
JavaScript npm, yarn, pnpm package.json, package-lock.json

Common commands

# Java
mvn install
mvn test
mvn dependency:tree

# Python
pip install requests
pip freeze > requirements.txt
pip install -r requirements.txt

# JavaScript
npm install axios
npm install --save-dev jest
npm test
npm run build

25. INTERVIEW Q&A — Common conceptual questions

Q1: Java vs Python — which is faster and why?

A: Java is faster because it compiles to bytecode and runs on the JVM with JIT optimization. Python is interpreted line by line. However, for I/O-bound tasks like API calls, the difference is negligible. For CPU-bound tasks, Java wins.

Q2: Why does Java have both int and Integer?

A: int is a primitive (8 bytes for an int including JVM overhead is misleading — int is just 4 bytes of data). Integer is an object wrapper used in collections (ArrayList<Integer> because generics need objects). Autoboxing converts between them automatically.

Q3: Why does Python use self explicitly?

A: Python is explicit by design — "explicit is better than implicit" (Zen of Python). self is the first parameter of every method and refers to the current instance. Other languages hide this as implicit this.

Q4: What's the difference between == and === in JS?

A: == does type coercion ("5" == 5 is true). === is strict ("5" === 5 is false). Always use === to avoid bugs.

Q5: Why is JavaScript single-threaded?

A: JS was designed for browsers where multi-threading would complicate the DOM. It uses an event loop with a single thread that handles callbacks asynchronously. For heavy computation, use Web Workers or worker threads in Node.

Q6: What is type hinting in Python — is it enforced?

A: Type hints are optional annotations (e.g., def add(a: int, b: int) -> int). The Python interpreter does NOT enforce them at runtime. Tools like mypy check them statically before deploy. Modern Python uses them extensively for IDE help and clarity.

Q7: What is the JVM?

A: Java Virtual Machine — runs Java bytecode on any platform (write once, run anywhere). Handles memory, GC, threading. Also runs Kotlin, Scala, Groovy.

Q8: Difference between let, const, var in JS?

A: var is function-scoped, hoisted, reassignable — legacy. let is block-scoped, not hoisted to top, reassignable. const is block-scoped, cannot be reassigned (but contents of objects can change). Modern code uses const by default, let when reassignment needed.

Q9: What is a closure?

A: A function that "remembers" variables from its outer scope, even after the outer function has returned.

function makeCounter() {
    let count = 0;
    return () => ++count;
}
const counter = makeCounter();
counter(); counter(); counter();  // 1, 2, 3 — count is "trapped"
Java has it too (via lambdas), Python via nested functions.

Q10: When would you choose Python over Java?

A: - Python for: scripting, data analysis, ML/AI, rapid prototyping, glue code - Java for: enterprise backend, Android, large team projects, performance-critical services


CHEAT SHEET — Quick syntax reference

Print

Java System.out.println(x);
Python print(x)
JS console.log(x);

Length of string

Java s.length()
Python len(s)
JS s.length

Convert to integer

Java Integer.parseInt("42")
Python int("42")
JS parseInt("42")

Loop 10 times

Java for (int i = 0; i < 10; i++)
Python for i in range(10):
JS for (let i = 0; i < 10; i++)

Array of 3 elements

Java int[] a = {1, 2, 3};
Python a = [1, 2, 3]
JS const a = [1, 2, 3];

Key-value pair

Java Map<String, Integer> m = new HashMap<>();
Python m = {"k": 1}
JS const m = { k: 1 };

Define a function

Java public int add(int a, int b) { return a + b; }
Python def add(a, b): return a + b
JS const add = (a, b) => a + b;

FINAL TIPS FOR SDETS

  1. Master one language deeply (Java or Python is best for SDETs) before being mediocre in three.
  2. Know the type system — interviewers love type-related gotchas.
  3. Know your data structures — interviewers will ask "ArrayList vs LinkedList?" or "Dict vs List?".
  4. Read other people's code — open source frameworks (Rest Assured, Playwright source) teach more than any tutorial.
  5. Practice writing small utilities — string parsers, file readers, retry wrappers. These mirror real SDET work.

Good luck refreshing the basics!