Java Notes
Deep dive into Java classes and objects — class anatomy, object creation, memory allocation, instance vs class members, and how objects work under the hood in the JVM.
A class is a blueprint or template that defines what data an entity holds and what operations it can perform. An object is a concrete instance of that class — a living, breathing entity in memory with actual values.
Think of it this way: a class is like an architectural blueprint for a house. The blueprint defines the structure — rooms, doors, windows. But you can't live in a blueprint. You need to actually *build* the house (create an object) to live in it. From one blueprint, you can build many houses, each painted differently and furnished uniquely.
Anatomy of a Java Class
A class has these components:
| Component | Purpose | Example |
|---|---|---|
| Fields | Store object state | private String brand; |
| Constructors | Initialize objects | public Car(String brand, ...) |
| Methods | Define behavior | public void accelerate() |
| Access Modifiers | Control visibility | private, public, protected |
| Nested Classes | Related helper types | class Engine { } inside Car |
Creating Objects — The new Keyword
Objects are created using the new keyword, which:
- Allocates memory on the heap
- Calls the constructor
- Returns a reference to the created object
public class Main {
public static void main(String[] args) {
// Creating objects
Car car1 = new Car("Toyota", "Camry", 2023);
Car car2 = new Car("Tesla", "Model 3", 2024);
Car car3 = new Car("Honda", "Civic", 2022);
// Using objects
car1.startEngine();
car1.accelerate(60);
car1.accelerate(30);
car1.brake();
System.out.println(car1);
System.out.println(car2);
}
}Toyota Camry engine started! Speed: 60.0 km/h Speed: 90.0 km/h Braking... Speed: 70.0 km/h 2023 Toyota Camry [70.0 km/h] 2024 Tesla Model 3 [0.0 km/h]
Memory Model: Stack vs Heap
Understanding where objects live in memory is crucial:
public class MemoryDemo {
public static void main(String[] args) {
int x = 10; // Primitive -> STACK
Car myCar = new Car("BMW", "X5", 2024); // Reference -> STACK, Object -> HEAP
Car anotherRef = myCar; // Both point to SAME object on heap
System.out.println(myCar == anotherRef); // true (same reference)
}
}Stack Memory:
- Stores local variables and references
- Fast, automatic cleanup when method returns
- Each thread has its own stack
Heap Memory:
- Stores all objects (created with
new) - Shared across threads
- Garbage collected when no references remain
Reference Variables vs Objects
This is a critical distinction many beginners miss:
public class ReferenceDemo {
public static void main(String[] args) {
// car1 is a REFERENCE variable, not the object itself
Car car1 = new Car("Audi", "A4", 2023);
// car2 now points to the SAME object as car1
Car car2 = car1;
// Modifying through car2 affects car1 (same object!)
car2.startEngine();
car2.accelerate(50);
System.out.println(car1.getSpeed()); // 50.0 — same object!
// Now car2 points to a NEW object
car2 = new Car("Mercedes", "C300", 2024);
// car1 still points to the original Audi
System.out.println(car1); // Audi A4
System.out.println(car2); // Mercedes C300
}
}Audi A4 engine started! Speed: 50.0 km/h 50.0 2023 Audi A4 [50.0 km/h] 2024 Mercedes C300 [0.0 km/h]
null — The Absence of an Object
A reference can point to nothing:
Car car = null; // Declared but points to no object
// This will crash! NullPointerException
car.startEngine(); // ❌ Cannot call methods on null
// Always check before using
if (car != null) {
car.startEngine();
}Instance Variables vs Local Variables
public class VariableScope {
// Instance variable - belongs to each object, lives on heap
private int instanceVar = 10;
// Static variable - belongs to class, shared by all objects
private static int classVar = 100;
public void method() {
// Local variable - lives on stack, dies when method ends
int localVar = 5;
System.out.println(instanceVar); // OK - accessing instance field
System.out.println(classVar); // OK - accessing class field
System.out.println(localVar); // OK - accessing local variable
}
public void anotherMethod() {
// System.out.println(localVar); // ❌ ERROR - localVar doesn't exist here
System.out.println(instanceVar); // OK - instance var accessible in all methods
}
}| Feature | Instance Variable | Local Variable | Static Variable |
|---|---|---|---|
| Declared in | Class body | Method/block | Class body with static |
| Default value | Yes (0, null, false) | No (must initialize) | Yes (0, null, false) |
| Lifetime | Object's lifetime | Method execution | Program's lifetime |
| Access | Via object reference | Within declaring method | Via class name |
| Memory | Heap (inside object) | Stack | Method area |
Multiple Objects from One Class
Each object has its own copy of instance variables:
Alice is studying Math Bob is studying Physics Total students: 3 Alice (Grade: 90) Charlie (Grade: 92)
Object as Method Parameters
Objects are passed by reference value — the method gets a copy of the reference, not a copy of the object:
public class PassByDemo {
public static void modifyObject(Car car) {
car.startEngine(); // Modifies the ORIGINAL object
car.accelerate(100); // This affects the caller's object
}
public static void reassignReference(Car car) {
car = new Car("Ford", "Mustang", 2024); // Only local reference changes
car.startEngine(); // This is the new Ford, not the original
}
public static void main(String[] args) {
Car myCar = new Car("Toyota", "Supra", 2023);
modifyObject(myCar);
System.out.println(myCar.getSpeed()); // 100.0 — object was modified!
reassignReference(myCar);
System.out.println(myCar); // Still Toyota Supra, not Ford Mustang
}
}Toyota Supra engine started! Speed: 100.0 km/h 100.0 Ford Mustang engine started! 2023 Toyota Supra [100.0 km/h]
Anonymous Objects
You can create objects without storing a reference:
public class AnonymousObjectDemo {
public static void main(String[] args) {
// Anonymous object - used once and discarded
new Car("BMW", "M3", 2024).startEngine();
// Useful for one-time operations
System.out.println(new String("hello").toUpperCase());
// Passing anonymous objects as arguments
printCarInfo(new Car("Porsche", "911", 2024));
}
public static void printCarInfo(Car car) {
System.out.println(car);
}
}Object Comparison: == vs equals()
public class ComparisonDemo {
public static void main(String[] args) {
Car car1 = new Car("Toyota", "Camry", 2023);
Car car2 = new Car("Toyota", "Camry", 2023);
Car car3 = car1;
// == compares REFERENCES (memory addresses)
System.out.println(car1 == car2); // false (different objects)
System.out.println(car1 == car3); // true (same object)
// equals() compares CONTENT (if properly overridden)
// Default equals() from Object class also uses ==
// You must override it for content comparison
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false (different objects)
System.out.println(s1.equals(s2)); // true (String overrides equals)
}
}false true false true
Real-World Example: Banking System
Invalid withdrawal: $3000.0 === Statement for John Doe === Account: ACC-001 Account opened with $1000.0 Deposited: $500.0 | Balance: $1500.0 Withdrew: $200.0 | Balance: $1300.0 Deposited: $1500.0 | Balance: $2800.0 Current Balance: $2800.0
Common Mistakes
- Confusing reference with object:
``java Car car1 = new Car("Toyota", "Camry", 2023); Car car2 = car1; // NOT a copy! Both point to same object ``
- Forgetting to initialize objects:
``java Car car; // Declared but not initialized car.startEngine(); // NullPointerException! ``
- Using == instead of equals() for content comparison:
``java String a = new String("test"); String b = new String("test"); if (a == b) { } // ❌ false — compares references if (a.equals(b)) { } // ✅ true — compares content ``
- Making all fields public:
``java public class Bad { public int age; // ❌ Anyone can set age = -5 } public class Good { private int age; // ✅ Controlled through setter public void setAge(int age) { if (age >= 0) this.age = age; } } ``
- Creating unnecessary objects:
``java // ❌ Creates new String object unnecessarily String s = new String("hello"); // ✅ Uses String pool String s = "hello"; ``
Best Practices
- One class per file — Keep classes in their own
.javafiles - Meaningful names —
CustomerOrdernotCOorObj1 - Encapsulate fields — Always use
privatewith getters/setters - Override
toString()— Makes debugging much easier - Override
equals()andhashCode()— When objects need content comparison - Favor immutability — Make fields
finalwhen possible - Keep classes focused — A class should represent ONE concept
Interview Questions
Q1: What is the difference between a class and an object? A class is a compile-time concept — a template that defines structure and behavior. An object is a runtime concept — an instance with actual data in memory.
Q2: Can you create an object without new? Yes — through reflection (Class.newInstance()), deserialization, cloning (clone()), or factory methods. But new is the standard way.
Q3: What happens when new Car() is called?
- Memory is allocated on the heap for the object
- Instance variables are set to default values
- Constructor is executed to initialize the object
- A reference to the object is returned
Q4: How many objects are created? String s = "hello"; It depends on the String pool. If "hello" already exists in the pool, zero new objects. If not, one object is created in the pool. Compare with new String("hello") which always creates a new object on the heap.
Q5: What is the default value of an object reference? null — it points to no object.
Q6: Can a class have no methods? Yes, it's valid but not useful in practice (called a POJO or data class). In modern Java, use record for pure data holders.
Q7: What is an immutable object? An object whose state cannot change after creation. All fields are final, no setters, and no references to mutable internal state are leaked. String is the classic example.
Q8: How many ways can you create an object in Java? Five ways: (1) new keyword, (2) Class.forName("...").newInstance() using reflection, (3) clone() method, (4) Deserialization (reading from file/network), (5) Factory methods. The new keyword is the most common and recommended approach.
Q9: What is the difference between instance variable and class variable? Instance variables belong to each object (different copy per object, stored on heap). Class variables (static) belong to the class itself (single copy shared by all objects, stored in method area). Instance variables are accessed via object reference; class variables via class name.
Q10: What is garbage collection in Java? Garbage collection is Java's automatic memory management. When an object has no references pointing to it, it becomes eligible for GC. The JVM periodically reclaims this memory. You can suggest GC with System.gc() but cannot force it. This prevents memory leaks common in C/C++.
Q11: What is the toString() method and why should you override it? toString() returns a string representation of an object. The default from Object class returns ClassName@hashcode which isn't useful. Overriding it provides meaningful output for debugging, logging, and display. It's automatically called in System.out.println(object).
Q12: Can an object reference itself? What happens with circular references? Yes, an object can have a field that references itself (like a linked list node). Circular references (A references B, B references A) don't cause memory leaks in Java because the garbage collector can detect and collect unreachable circular reference groups.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Class and Object in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, oops, class, and
Related Java Master Course Topics