Quiz 2

Classes & Objects — Constructors, this, static Members

2625 words
13 min read
Python Week 1: the first filter for runtime behavior
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 new keyword
  • Write multiple constructor overloads with constructor chaining
  • Understand the this reference and when to use it explicitly
  • Distinguish between static and instance members
  • Control object initialization with initializer blocks

📋 Prerequisites


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:
java
class 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

java
public 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)

java
Student 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:
  1. Allocates memory on the heap
  2. Calls the constructor to initialize the object
  3. Returns the reference (memory address)

3. Constructors

3.1 Constructor Rules

java
public 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

java
public 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:
java
public 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

java
public 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(...):
java
public 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:
java
public 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

java
public 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

java
public class Event {
    public void register() {
        EventManager.add(this);  // Pass current object
    }
}

5. Static Members

5.1 Static Fields (Class Variables)

java
public 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

java
public class MathConstants {
    public static final double PI = 3.14159265359;
    public static final double E = 2.71828182846;
}
// MathConstants.PI — accessible everywhere

5.3 Static Methods

java
public 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:
java
public 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:
  1. Static initializer blocks (in order of appearance) — runs once when class loads
  2. Instance initializer blocks (in order of appearance) — runs before constructor body
  3. Constructor body — runs last
java
public 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

FeatureJavaPython
Class definitionpublic class ClassNameclass ClassName:
Constructorpublic ClassName(params)def __init__(self, params)
this/selfthis (implicit, optional)self (explicit first parameter)
new keywordRequired: new ClassName()Implicit: ClassName()
Multiple constructorsOverloading (different signatures)Default args or @classmethod
Instance fieldsDeclared in class bodyAssigned in __init__
Static fieldsstatic keywordDeclared at class level outside methods
Static methodsstatic keyword@staticmethod decorator
Method overloadingSupported (compile-time)Not directly (default args)

8. Common Pitfalls

Pitfall 1: Forgetting new

java
Student 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

java
public 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

java
public 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

java
public 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

java
public 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?
java
class 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: 0
When new B() runs: B's constructor calls A's constructor (via super()). A's constructor calls show(), which is overridden in B (dynamic dispatch). At this point, B's x hasn't been initialized yet (still default 0). So it prints "B: 0", then B's x is set to 20 after the parent constructor returns. Q2: What is wrong with this code?
java
public class Main {
    private int value;
    public Main(int value) {
        value = value;  // ???
    }
}
Answer: value = value; is a self-assignment — the parameter value assigns to itself, leaving the field value at its default (0). Fix: this.value = value; Q3: What does this() 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.
java
public 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:
  1. Singleton pattern: Only one instance exists
  2. Utility classes: All methods are static (like Math)
  3. Factory methods: Control object creation
java
public 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?
java
class 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 3
Static block runs once when class loads ("1"). First new Test(): instance block ("2"), then constructor ("3"). Second new Test(): instance block ("2") again, constructor ("3") again. Static block does NOT run again. Q6: What is the effect of static on a field?
Answer: A static field 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:
java
public 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 call new 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 demonstrating this() chaining.
Answer:
java
public 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?
java
public 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 30
o.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

ConceptSyntaxPurpose
Class declarationpublic class Name { }Define a blueprint
Object creationnew ClassName(args)Instantiate an object
Constructorpublic Name(params) { }Initialize object state
thisthis.fieldReference current object
this()this(args)Call another constructor
static fieldstatic type nameClass-level (shared) data
static methodstatic type name() { }Class-level behavior
Instance block{ }Code before constructor
Static blockstatic { }Class initialization once

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.