Java Course
Java Crash Course
The Essential Reference Guide for Beginners
1. Hello World & Program Structure
Every Java program starts with a class containing a main method — the entry point the JVM calls when you run the program.
public class HelloWorld {
// The entry point — JVM starts here
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}Key Rule
The file name must match the class name exactly — case-sensitive. HelloWorld.java must contain public class HelloWorld.
2. Variables & Data Types
Java is statically typed — you must declare a variable's type before using it.
// Primitive types
int age = 25;
double gpa = 3.85;
boolean active = true;
char grade = 'A';
long bigNum = 9_000_000_000L; // L suffix for long
float price = 9.99f; // f suffix for float
// Reference type — String is a class, not a primitive
String name = "Ayman";
// var — type inferred by compiler (Java 10+)
var score = 95; // inferred as int
var message = "Hello"; // inferred as String
// Constants — use final
final double PI = 3.14159;Tip
Use final for values that should never change. By convention, constant names are UPPER_SNAKE_CASE.
3. Operators
// Arithmetic
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3 (integer division)
System.out.println(a % b); // 1 (remainder)
// Compound assignment
a += 5; // a = a + 5
a++; // a = a + 1
// Comparison (returns boolean)
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a >= b); // true
// Logical
System.out.println(true && false); // false
System.out.println(true || false); // true
System.out.println(!true); // false
// String concatenation
String msg = "Score: " + 95; // "Score: 95"4. Control Flow
int score = 85;
// if / else if / else
if (score >= 90) {
System.out.println("Grade: A");
} else if (score >= 80) {
System.out.println("Grade: B"); // ← this runs
} else {
System.out.println("Grade: F");
}
// Ternary operator
String result = (score >= 60) ? "Pass" : "Fail";
// Switch expression (Java 14+)
String letter = switch (score / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
default -> "F";
};Modern Java
The arrow -> switch expression (Java 14+) is cleaner than the old case X: break; pattern — no fall-through bugs.
5. Loops
// for loop
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
// while loop
int count = 0;
while (count < 3) {
System.out.println("count = " + count);
count++;
}
// do-while — always executes at least once
do {
System.out.println("runs once minimum");
} while (false);
// Enhanced for-each loop
int[] nums = {10, 20, 30};
for (int n : nums) {
System.out.println(n);
}6. Arrays & ArrayLists
// Fixed-size array
int[] scores = {90, 85, 78, 92};
System.out.println(scores[0]); // 90
System.out.println(scores.length); // 4
// Dynamic ArrayList (import required)
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
names.add("Ayman");
names.add("Sara");
names.add("Ali");
System.out.println(names.get(0)); // "Ayman"
System.out.println(names.size()); // 3
names.remove("Sara");
System.out.println(names.contains("Ali")); // true
// Iterate with for-each
for (String name : names) {
System.out.println(name);
}Tip
Use arrays when size is fixed and performance is critical. Use ArrayList when you need to add/remove items dynamically.
7. Methods
public class MathUtils {
// Static method — call without creating an object
public static int add(int a, int b) {
return a + b;
}
// Method overloading — same name, different parameters
public static double add(double a, double b) {
return a + b;
}
// Varargs — variable number of arguments
public static int sum(int... nums) {
int total = 0;
for (int n : nums) total += n;
return total;
}
public static void main(String[] args) {
System.out.println(add(3, 4)); // 7
System.out.println(add(1.5, 2.5)); // 4.0
System.out.println(sum(1, 2, 3, 4)); // 10
}
}8. OOP & Classes
public class Student {
// Instance fields — private for encapsulation
private String name;
private int grade;
// Constructor
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
// Getter
public String getName() { return name; }
public int getGrade() { return grade; }
// Instance method
public String letterGrade() {
return switch (grade / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
default -> "F";
};
}
// toString — called automatically by println
@Override
public String toString() {
return name + " → " + letterGrade() + " (" + grade + ")";
}
}
// Usage
Student s = new Student("Ayman", 92);
System.out.println(s); // Ayman → A (92)
System.out.println(s.getName()); // Ayman9. Inheritance & Polymorphism
// Parent class
public class Animal {
protected String name;
public Animal(String name) { this.name = name; }
public String speak() { return "..."; }
@Override
public String toString() { return name; }
}
// Child class — extends inherits all parent members
public class Dog extends Animal {
public Dog(String name) { super(name); } // call parent constructor
@Override
public String speak() { return "Woof!"; }
}
public class Cat extends Animal {
public Cat(String name) { super(name); }
@Override
public String speak() { return "Meow!"; }
}
// Polymorphism — same type, different behaviour
Animal[] animals = { new Dog("Rex"), new Cat("Luna") };
for (Animal a : animals) {
System.out.println(a + ": " + a.speak());
}
// Rex: Woof!
// Luna: Meow!10. Interfaces
An interface defines a contract — a set of methods a class promises to implement. A class can implement multiple interfaces.
// Define an interface
public interface Printable {
void print(); // implicitly public abstract
}
public interface Saveable {
boolean save(String path);
}
// Implement multiple interfaces
public class Document implements Printable, Saveable {
private String content;
public Document(String content) { this.content = content; }
@Override
public void print() {
System.out.println(content);
}
@Override
public boolean save(String path) {
System.out.println("Saving to: " + path);
return true;
}
}Interface vs Abstract Class
Use an interface when unrelated classes share behaviour (e.g. both Dog and Document can be Printable). Use an abstract class when related classes share code and state.
11. Exception Handling
// try-catch-finally
try {
int result = 10 / 0; // throws ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
} finally {
System.out.println("Always runs");
}
// Multiple catch blocks
try {
String s = null;
s.length(); // NullPointerException
} catch (NullPointerException e) {
System.out.println("Null value!");
} catch (Exception e) {
System.out.println("General error: " + e);
}
// Custom exception
public class InvalidGradeException extends RuntimeException {
public InvalidGradeException(int grade) {
super("Invalid grade: " + grade);
}
}
// Throw it
if (grade < 0 || grade > 100) {
throw new InvalidGradeException(grade);
}Warning
Never catch Exception or Throwable as a general catch-all in production — you'll swallow errors silently. Catch the most specific exception type possible.
12. Generics
Generics let you write type-safe code that works with any data type, eliminating the need for casting and catching ClassCastException at runtime.
// Generic class — T is a type parameter
public class Box<T> {
private T value;
public Box(T value) { this.value = value; }
public T getValue() { return value; }
@Override
public String toString() { return "Box[" + value + "]"; }
}
// Usage — compiler enforces types
Box<String> sBox = new Box<>("Hello");
Box<Integer> iBox = new Box<>(42);
System.out.println(sBox); // Box[Hello]
System.out.println(iBox); // Box[42]
// Generic method
public static <T extends Comparable<T>> T max(T a, T b) {
return (a.compareTo(b) >= 0) ? a : b;
}
System.out.println(max(10, 20)); // 20
System.out.println(max("apple", "mango")); // mango