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!");
}
}
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¶
Why simple? Python is designed for readability. No class wrapper required. The interpreter runs from top to bottom.JavaScript¶
Whyconsole.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
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)
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
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?¶
- Performance — immutable objects can be safely shared between threads
- Bugs — passing mutable objects to functions can cause unexpected side effects
- 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!
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
delto 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"
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¶
- Master one language deeply (Java or Python is best for SDETs) before being mediocre in three.
- Know the type system — interviewers love type-related gotchas.
- Know your data structures — interviewers will ask "ArrayList vs LinkedList?" or "Dict vs List?".
- Read other people's code — open source frameworks (Rest Assured, Playwright source) teach more than any tutorial.
- Practice writing small utilities — string parsers, file readers, retry wrappers. These mirror real SDET work.
Good luck refreshing the basics!