Classes & Objects — Constructors, this, static Members
2625 words
13 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Classes & Objects — Constructors, this, static Members ## 🎯 Learning Objectives By the end of this topic, you will be able to: - Define classes with fields, constructors, and methods - Instantiate objects using the `new` keyword - Write multiple constructor overloads with constructor chaining - Understand the `th...

Classes & Objects — Constructors, this, static Members
🎯 Learning Objectives
By the end of this topic, you will be able to:
- Define classes with fields, constructors, and methods
- Instantiate objects using the
newkeyword - Write multiple constructor overloads with constructor chaining
- Understand the
thisreference and when to use it explicitly - Distinguish between static and instance members
- Control object initialization with initializer blocks
📋 Prerequisites
- OOP Concepts (week01/05-oop-concepts.md): Encapsulation, abstraction
- Memory Model (week01/03-memory-model.md): Stack, heap, references
- BSCS1002 — Python: Python class definitions
1. Intuition: What Problem Does This Solve?
1.1 The Problem
Without classes, related data and behavior are scattered:
java// Procedural approach — data and functions are separate String empName = "Alice"; double empSalary = 50000; void giveRaise(String name, double amount) { ... }
With classes, they're bundled together:
javaclass Employee { String name; double salary; void giveRaise(double amount) { this.salary += amount; } }
1.2 Mental Model: A Blueprint and Its Houses
A class is the blueprint for a house. The blueprint defines:
- What properties the house has (fields): number of rooms, color, square footage
- What the house can do (methods): open door, turn on lights, close windows The object (instance) is the actual house built from that blueprint. You can build many houses from one blueprint, each with its own state:
- House 1: {color: "blue", rooms: 3}
- House 2: {color: "white", rooms: 4}
2. Class Declaration
2.1 Basic Structure
javapublic class Student { // Fields (state) String name; int rollNumber; double gpa; // Constructors (initialization) public Student(String name, int rollNumber) { this.name = name; this.rollNumber = rollNumber; this.gpa = 0.0; } // Methods (behavior) public void displayInfo() { System.out.println("Name: " + name + ", Roll: " + rollNumber); } public void updateGPA(double newGPA) { if (newGPA >= 0.0 && newGPA <= 10.0) { this.gpa = newGPA; } } }
2.2 Creating Objects (Instantiation)
javaStudent s1 = new Student("Alice", 101); Student s2 = new Student("Bob", 102); s1.updateGPA(8.5); s1.displayInfo(); // Name: Alice, Roll: 101 s2.displayInfo(); // Name: Bob, Roll: 102
The
new keyword:- Allocates memory on the heap
- Calls the constructor to initialize the object
- Returns the reference (memory address)
3. Constructors
3.1 Constructor Rules
javapublic class BankAccount { private String accountNumber; private double balance; // Constructor: same name as class, no return type public BankAccount(String accountNumber) { this.accountNumber = accountNumber; this.balance = 0.0; } }
Rules:
- Constructor name MUST match the class name
- No return type (not even
void) - Called automatically with
new - If you define NO constructor, Java provides a default no-arg constructor
3.2 Default Constructor
javapublic class Simple { // Java provides: public Simple() { } // invisible default } // Usage: Simple s = new Simple(); // OK
If you define ANY constructor, the default no-arg constructor disappears:
javapublic class Example { private int x; public Example(int x) { this.x = x; } // NO default constructor anymore! } // Example e = new Example(); // Compile error! // Example e = new Example(5); // OK
3.3 Constructor Overloading
javapublic class Rectangle { private double length; private double width; // No-arg constructor public Rectangle() { this.length = 1.0; this.width = 1.0; } // Two-arg constructor public Rectangle(double length, double width) { this.length = length; this.width = width; } // Square constructor public Rectangle(double side) { this.length = side; this.width = side; } } // Usage: Rectangle r1 = new Rectangle(); // 1x1 Rectangle r2 = new Rectangle(5, 3); // 5x3 Rectangle r3 = new Rectangle(4); // 4x4 (square)
3.4 Constructor Chaining with this()
One constructor can call another using
this(...):javapublic class Employee { private String name; private int id; private String department; // Most specific constructor public Employee(String name, int id, String department) { this.name = name; this.id = id; this.department = department; } // Delegates to the 3-arg constructor public Employee(String name, int id) { this(name, id, "Unknown"); // Must be first statement } // Delegates to the 2-arg constructor public Employee() { this("Unknown", 0); // Must be first statement } }
Rules for
this():- Must be the first statement in the constructor
- Can only be used in constructors
- Creates a chain — the leaf constructor does the actual work
4. The this Reference
4.1 Disambiguating Field Names
The most common use of
this is to distinguish between parameters and fields with the same name:javapublic class Point { private int x; private int y; public Point(int x, int y) { this.x = x; // this.x = field, x = parameter this.y = y; } }
Without
this, the assignment x = x would be a no-op (the parameter assigns to itself).4.2 Calling Methods on the Current Object
javapublic class Builder { public Builder setValue(int val) { // process val return this; // Return current object for chaining } } // Usage: method chaining Builder b = new Builder(); b.setValue(10).setValue(20).setValue(30); // Fluent API
4.3 Passing Current Object to Another Method
javapublic class Event { public void register() { EventManager.add(this); // Pass current object } }
5. Static Members
5.1 Static Fields (Class Variables)
javapublic class Counter { public static int count = 0; // Shared by ALL instances private int instanceNumber; public Counter() { count++; // Increment shared counter instanceNumber = count; // Each instance gets unique number } } // Usage: Counter c1 = new Counter(); // count = 1 Counter c2 = new Counter(); // count = 2 Counter c3 = new Counter(); // count = 3 System.out.println(Counter.count); // 3 (accessed via class name) System.out.println(c1.count); // 3 (also works, but discouraged)
(Diagram)
5.2 Static Constants
javapublic class MathConstants { public static final double PI = 3.14159265359; public static final double E = 2.71828182846; } // MathConstants.PI — accessible everywhere
5.3 Static Methods
javapublic class MathUtils { public static int max(int a, int b) { return (a > b) ? a : b; } public static boolean isEven(int n) { return n % 2 == 0; } } // Usage: no object needed int largest = MathUtils.max(10, 20); boolean even = MathUtils.isEven(7);
Static method rules:
- Can only access static fields/methods directly
- Cannot use
this(no current object) - Cannot access instance fields/methods without an object reference
- Common use: utility/helper methods
5.4 Static Initializer Block
Runs once when the class is first loaded:
javapublic class Database { private static String connectionString; private static int maxConnections; static { // Runs when class is loaded System.out.println("Loading Database configuration..."); connectionString = System.getenv("DB_CONNECTION"); maxConnections = 10; } }
6. Instance vs Static Initialization Order
When an object is created, initialization happens in this order:
- Static initializer blocks (in order of appearance) — runs once when class loads
- Instance initializer blocks (in order of appearance) — runs before constructor body
- Constructor body — runs last
javapublic class InitOrder { static { System.out.println("1: static block"); } { System.out.println("2: instance block"); } public InitOrder() { System.out.println("3: constructor"); } public static void main(String[] args) { new InitOrder(); new InitOrder(); } } // Output: // 1: static block (runs once) // 2: instance block (runs each instantiation) // 3: constructor // 2: instance block (second object) // 3: constructor
7. Java vs Python: Classes & Objects
| Feature | Java | Python |
|---|---|---|
| Class definition | public class ClassName | class ClassName: |
| Constructor | public ClassName(params) | def __init__(self, params) |
this/self | this (implicit, optional) | self (explicit first parameter) |
new keyword | Required: new ClassName() | Implicit: ClassName() |
| Multiple constructors | Overloading (different signatures) | Default args or @classmethod |
| Instance fields | Declared in class body | Assigned in __init__ |
| Static fields | static keyword | Declared at class level outside methods |
| Static methods | static keyword | @staticmethod decorator |
| Method overloading | Supported (compile-time) | Not directly (default args) |
8. Common Pitfalls
Pitfall 1: Forgetting new
javaStudent s = Student("Alice", 101); // Compile error!
Why: In Java, objects are created with
new. Constructor call without new is invalid. Fix: Student s = new Student("Alice", 101);Pitfall 2: Shadowing with Parameters
javapublic class Student { String name; public Student(String name) { name = name; // No-op! Parameter assigns to itself } }
Why: Without
this, the parameter name shadows the field. name = name is a self-assignment. Fix: this.name = name;Pitfall 3: Calling Instance Methods from Static Context
javapublic class Test { private int x = 5; public static void main(String[] args) { System.out.println(x); // Compile error! } }
Why:
main is static; x is an instance field. No object exists when main starts. Fix: Create an object first: new Test().x or make x static.Pitfall 4: Accidentally Using static for Instance Data
javapublic class Student { private static int id; // Should be instance field! }
Why: All students would share the same
id. Every new student overwrites the previous one. Fix: Remove static to make it an instance field.Pitfall 5: Constructor Calling Overridable Method
javapublic class Parent { public Parent() { init(); // Calls CHILD's init() before child is initialized! } void init() { System.out.println("Parent init"); } } class Child extends Parent { private int value = 42; void init() { System.out.println("Child init: " + value); } // Prints 0! }
Why: During parent constructor execution, the child object isn't fully initialized yet. Never call overridable methods from constructors.
9. Practice Questions
Q1: What is the output?javaclass A { int x = 10; public A() { show(); } void show() { System.out.println("A: " + x); } } class B extends A { int x = 20; void show() { System.out.println("B: " + x); } } public class Test { public static void main(String[] args) { B b = new B(); } }Answer:B: 0Whennew B()runs: B's constructor calls A's constructor (viasuper()). A's constructor callsshow(), which is overridden in B (dynamic dispatch). At this point, B'sxhasn't been initialized yet (still default 0). So it prints "B: 0", then B'sxis set to 20 after the parent constructor returns. Q2: What is wrong with this code?javapublic class Main { private int value; public Main(int value) { value = value; // ??? } }Answer:value = value;is a self-assignment — the parametervalueassigns to itself, leaving the fieldvalueat its default (0). Fix:this.value = value;Q3: What doesthis()do in a constructor?Answer:this()calls another constructor in the same class. It must be the first statement in the calling constructor. It enables constructor chaining — one constructor delegates to another with a different parameter list, avoiding code duplication.javapublic class Point { int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public Point() { this(0, 0); } // Calls the 2-arg constructor }Q4: Can a constructor be private? What's the use case?Answer: Yes! A private constructor prevents external instantiation. Use cases:
- Singleton pattern: Only one instance exists
- Utility classes: All methods are static (like
Math)- Factory methods: Control object creation
javapublic class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } // Can't call from outside public static Singleton getInstance() { return instance; } }Q5: What is the output?javaclass Test { static { System.out.print("1 "); } { System.out.print("2 "); } public Test() { System.out.print("3 "); } } public class Main { public static void main(String[] args) { new Test(); new Test(); } }Answer:1 2 3 2 3Static block runs once when class loads ("1"). Firstnew Test(): instance block ("2"), then constructor ("3"). Secondnew Test(): instance block ("2") again, constructor ("3") again. Static block does NOT run again. Q6: What is the effect ofstaticon a field?Answer: Astaticfield is shared by ALL instances of the class. It belongs to the class, not to any particular object. It's initialized when the class is loaded, and there's only one copy in memory regardless of how many objects exist.Usage: Class constants (static final), counters, shared configuration. Q7: Can a static method access an instance variable? Why or why not?Answer: No, a static method cannot directly access an instance variable. When a static method runs, there may be no instance of the class at all. The static method doesn't know which object's instance variable to access. To access instance variables from a static method, you must pass an object reference:javapublic class Foo { int x = 5; public static void main(String[] args) { Foo f = new Foo(); System.out.println(f.x); // OK — explicit object } }Q8: What is a default constructor? When does it disappear?Answer: The default constructor is a no-arg constructor Java provides automatically if you define NO constructors. It's invisible — you just callnew ClassName(). The default constructor:
- Has no parameters
- Has empty body
- Calls
super()(parent's no-arg constructor)It disappears as soon as you define ANY constructor. After that,new ClassName()will fail unless you explicitly define a no-arg constructor. Q9: Write a class with overloaded constructors demonstratingthis()chaining.Answer:javapublic class Book { private String title; private String author; private int pages; public Book(String title, String author, int pages) { this.title = title; this.author = author; this.pages = pages; } public Book(String title, String author) { this(title, author, 0); // Unknown page count } public Book(String title) { this(title, "Unknown"); // Unknown author } public Book() { this("Untitled"); // Completely unknown } }Q10: What is the output?javapublic class Outer { int x = 10; static int y = 20; class Inner { int x = 30; } public static void main(String[] args) { Outer o = new Outer(); Outer.Inner i = o.new Inner(); System.out.println(o.x + " " + y + " " + i.x); } }Answer:10 20 30o.x= 10 (outer field),y= 20 (static field, accessed without class name since we're in the class),i.x= 30 (inner's field).
📐 Key Concepts
| Concept | Syntax | Purpose |
|---|---|---|
| Class declaration | public class Name { } | Define a blueprint |
| Object creation | new ClassName(args) | Instantiate an object |
| Constructor | public Name(params) { } | Initialize object state |
this | this.field | Reference current object |
this() | this(args) | Call another constructor |
static field | static type name | Class-level (shared) data |
static method | static type name() { } | Class-level behavior |
| Instance block | { } | Code before constructor |
| Static block | static { } | Class initialization once |
🔗 Cross-References
- Next: Inheritance
- Related: OOP Concepts
- Python Comparison: BSCS1002 — Classes in Python Join Discord Previous2.2 StringsNext3.1 Inheritance