L
LLLOS.ai
Learn
L

Chapter 6 — Constructors

Class 10 · Computer Applications

Overview

This unit explains constructors in object-oriented programming with a focus on Java as used in ICSE Class 10 Computer Applications. A constructor is a special method-like block used to create and initialise objects. Students learn why constructors differ from regular methods, how default and parameterised constructors work, and how constructor overloading helps create flexible code. The unit also covers copy constructors, constructor chaining using this() and super(), access modifiers for constructors, and rules such as when the compiler supplies a default constructor. Practical examples and small programs illustrate when to use constructors to set initial values, validate input, or manage resources. Understanding constructors matters because object creation and correct initialization are central to designing reliable programs. Good use of constructors reduces bugs, clarifies class usage, and prepares students for later topics like inheritance, polymorphism, and design patterns. By the end of the unit, students will be able to write classes with appropriate constructors, choose between default and parameterised forms, overload constructors, and apply constructor chaining to reuse code and maintain clean class design.

Learning Objectives

  • Explain what a constructor is and how it differs from a method.
  • Identify when the Java compiler provides a default constructor.
  • Write classes with default and parameterised constructors to initialise object state.
  • Apply constructor overloading to support multiple ways of creating objects.
  • Use this() to implement constructor chaining within a class.
  • Use super() to invoke a parent class constructor in an inheritance hierarchy.
  • Describe and implement a copy constructor to duplicate objects safely.
  • Apply access modifiers to constructors and explain their effect on object creation.
  • Detect and correct common constructor-related errors in small Java programs.

Topics in this chapter

15 topics · tap a topic title to jump straight to it.

💻1

What is a Constructor

Definition and purpose
A constructor is a special block within a class that runs automatically when an object of that class is created. Its main job is to set the new object into a valid starting state by giving initial values to fields, performing basic checks and preparing any required internal resources. Unlike ordinary methods, constructors have the exact same name as the class and do not declare any return type.

Appearance and basic rules
The syntax looks like a method header but without a return type: ClassName(parameters) { body }. A constructor can have access modifiers (public, private, protected or default) and it can take parameters or none. If no constructor is written by the programmer, most compilers supply a default no-argument constructor automatically.

When it runs
The constructor runs as part of the new operation. Writing new ClassName(...) allocates memory for the object and then immediately executes the chosen constructor. After the constructor finishes, the object is ready for use by other code.

Role in object lifecycle
The constructor is the first instance code that runs for an object. It is the place to enforce class invariants—conditions that must always hold true for the object. For example, a BankAccount constructor may ensure the balance starts non-negative. Keeping such checks in constructors prevents invalid objects propagating through the program.

Good practices
Keep constructors focused on initialisation, not on long computations or I/O. If object creation requires complex steps, consider factory methods or helper methods called from the constructor. Use clear parameter names and this.field when a parameter name shadows a field. Avoid side-effects visible outside the object during construction unless intended.

Common misconceptions
Students sometimes expect constructors to return values or think they are ordinary methods; remember the key differences: name equals class name and there is no return type. Also, constructors cannot be inherited so each class should declare any constructors it needs or call an appropriate parent constructor when extending another class.

Summary
A constructor is the canonical way to prepare a newly created object so it is ready, safe and predictable to use. Mastering constructors is an important step toward designing correct, maintainable classes.

📌 Examples
  • class Box { int width; Box() { width = 10; } } creates an object with width 10
  • class Lamp { boolean on; Lamp() { on = false; } } initialises state
  • Creating an object: Box b = new Box(); runs Box() constructor
  • Incorrect: public void Box() { } is not a constructor because it has a return type
🧮 Formulas
  1. Constructor name = Class name
  2. Constructor has no return type
  3. Object creation: ClassName ref = new ClassName(arguments);
📊 Visual ideas
Diagram showing memory: Class template on left, new object on heap on right with fields initialised by constructor, and reference variable pointing to object
💻2

Default Constructor

Definition and compiler behaviour
A default constructor is a no-argument constructor that the compiler provides automatically if the programmer does not write any constructor for the class. It allows objects to be created without providing initial values explicitly. The compiler-created default constructor performs the standard default initialisation for fields: numeric types become 0, boolean becomes false, char becomes '\u0000', and object references become null.

When the compiler supplies it
If the class body contains no constructor at all, the compiler inserts an implicit no-arg constructor. This ensures that code using new ClassName() compiles and runs. The inserted constructor has the same access as the class and contains an empty body apart from the normal initialisation of fields.

When it is not supplied
The moment any constructor is explicitly written by the programmer, even a parameterised one, the compiler will not generate the default constructor. That means calls to new ClassName() will fail to compile unless you also write a no-arg constructor yourself. This common source of errors arises when someone adds a parameterised constructor and forgets to add a no-argument form that other parts of the program expect.

Practical implications
Many frameworks and serialization tools require a no-arg constructor so they can create objects reflectively. If your class is to be used by libraries or stored and restored, provide a public or protected no-arg constructor as needed. Conversely, deliberately omitting a no-arg constructor is a way to force callers to supply necessary data during object creation.

Design advice
If your class needs both the convenience of quick creation and the safety of initial values, define both constructors explicitly: one no-arg setting sensible defaults and one or more parameterised constructors. This makes the class API clear and avoids surprises when other code tries to create objects without parameters.

Example explanation
Consider class Person { String name; int age; } with no constructors: the compiler adds Person() so new Person() works. If you later add Person(String n) { name = n; } then Person() is no longer available automatically; add Person() { name = "Unknown"; age = 0; } if you still want it.

Summary
Understanding when a default constructor is or is not provided helps avoid compile-time errors and informs API design choices for classes intended for reuse.

📌 Examples
  • class A { } // compiler creates A()
  • class B { B(int x) { } } // compiler does NOT create B()
  • If you need both: class C { C() { } C(int x) { } }
  • Creating: A a = new A(); works due to default constructor
🧮 Formulas
  1. If no constructor written by programmer => compiler provides a default no-arg constructor
📊 Visual ideas
Flowchart: Class has no constructors? -> Yes -> Compiler inserts default constructor -> Object created using new ClassName()
💻3

Parameterised Constructors

Purpose and benefit
Parameterised constructors accept arguments that supply initial values for the object's fields. They enable creation of objects that begin life with meaningful and required data, thus reducing the need for separate setter calls after creation. They are especially useful when certain fields must have values for the object to be valid.

Syntax and behaviour
A parameterised constructor has parameters like a method: ClassName(type1 p1, type2 p2) { ... }. Inside the constructor body you typically assign parameter values to instance fields. When a parameter name is the same as a field name, use this.field to refer to the field; otherwise the parameter shadows the field.

Validation and invariants
Constructors are the right place to check that provided arguments are sensible. For instance, if a class stores age, checking that the passed age is non-negative prevents the object from existing in an invalid state. If validation fails, throw an appropriate exception such as IllegalArgumentException which signals the calling code about incorrect usage.

Multiple constructor forms
Often a class will provide several constructors to allow different levels of detail at creation time. For example, a Book class might offer Book(String title) and Book(String title, String author, int price). The available parameterised forms are selected by the compiler based on the arguments used in new expressions.

Practical patterns
Use this(...) chaining to centralise initialisation and avoid repeating assignments across constructors. Keep parameter lists concise and document each constructor’s purpose so users of the class know which form to choose. For reference-type fields, decide whether the constructor should copy mutable input objects or hold references to them; copying improves encapsulation.

Common mistakes
Do not declare a return type for a constructor. Check that you write parentheses when calling the constructor with new. Also ensure the types and number of arguments match a constructor signature; otherwise compilation fails.

Example
class Point { int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } Creating Point p = new Point(3, 4) sets fields immediately so p is ready for use.

📌 Examples
  • class Point { int x,y; Point(int x, int y) { this.x = x; this.y = y; } }
  • Creating: Point p = new Point(3,4); initialises p.x=3, p.y=4
  • Validating: Person(String n, int a) { if(a<0) throw new IllegalArgumentException("age"); age = a; }
  • Using this: this.name = name to distinguish field from parameter
🧮 Formulas
  1. Use this.field to refer to instance field when shadowed by a parameter
📊 Visual ideas
A diagram of constructor call: new Class(arg1, arg2) -> parameter values flow into constructor, fields assigned accordingly
💻4

Constructor Overloading

Concept
Constructor overloading means defining multiple constructors in the same class that have different parameter lists. Each constructor offers a different way to create and initialise an object. Overloading provides flexibility to the class user: you can create an object with default values, with some values supplied, or with full control of all fields.

How the compiler resolves calls
When new ClassName(arguments) is used, the compiler matches the number and types of the provided arguments to the parameter lists of available constructors. The best matching one is selected. If no matching signature exists, the code will not compile. Therefore carefully design constructor signatures to avoid ambiguous matches.

Design patterns
A common pattern is to define a full constructor that sets all fields and then provide simpler constructors that call the full one with default values using this(...). This keeps a single place for main initialisation and reduces duplication. For example: Book() { this("Unknown", "Unknown", 0); } Book(String t) { this(t, "Unknown", 0); } Book(String t, String a, int p) { title=t; author=a; price=p; }

Practical advantages
Overloading improves usability. Callers may use a convenient no-arg constructor when defaults are fine, or use a parameterised one when particular values are needed. Overloading also supports gradual addition of functionality: start with a simple constructor and add more detailed ones as requirements grow.

Pitfalls and clarity
Avoid creating constructors whose parameter types differ only by types that can be implicitly converted, as this can lead to ambiguity. Document each constructor clearly in comments. Also remember that adding a parameterised constructor removes the automatic default no-arg constructor, so add a no-arg form if code relies on it.

Example
class Rectangle { Rectangle() { this(1,1); } Rectangle(int side) { this(side, side); } Rectangle(int w, int h) { width=w; height=h; } } This shows three creation options for the same logical object.

📌 Examples
  • Rectangle r1 = new Rectangle(); // default
  • Rectangle r2 = new Rectangle(5); // square 5x5
  • Rectangle r3 = new Rectangle(4,6); // width 4 height 6
  • Overloaded constructors often call each other using this(...)
🧮 Formulas
  1. Overloading requires different parameter lists: number, order, or types must differ
  2. this(arguments) can be used to call another constructor in the same class
📊 Visual ideas
Table showing constructor signatures in one column and usage examples in another to match which call invokes which constructor
💻5

Constructor Chaining with this()

What is chaining?
Constructor chaining is a technique where one constructor calls another constructor in the same class to reuse initialisation code. In Java this is done using the this(...) syntax. Chaining reduces duplicated assignments and centralises the logic that sets up the object.

Syntax and strict rule
The call this(arguments) must be the first statement in the constructor. No other statements may appear before it. If a constructor does not call this(...), it may still call super(...) or rely on implicit parent constructor calls. Because this(...) must be first, you cannot use both this(...) and super(...) in the same constructor.

Typical pattern
A recommended pattern is to implement a primary constructor that does complete initialisation, and then provide simpler constructors that call the primary one with default values. For example: Employee() { this("Unknown", 0, 0.0); } Employee(String n) { this(n, 0, 0.0); } Employee(String n,int id,double sal) { name=n; this.id=id; salary=sal; } All constructors funnel into the three-argument constructor.

Benefits
Chaining ensures consistent initialisation: every constructor follows the same path to set fields. This simplifies maintenance because bug fixes or validation rules need to be changed only in the primary constructor. It also clarifies default values used by simpler constructors.

Common mistakes
Placing other code before this(...) causes a compile-time error. Attempting to create circular chaining such as A() calls B() and B() calls A() will also cause a compile error. Another mistake is trying to use this(...) to call a parent constructor; this(...) only calls constructors in the same class.

Practical tips
Keep the primary constructor small and well-tested. Use descriptive parameter names and document which constructor is the main initialiser. For constructors that perform validation, either validate only in the primary constructor or ensure each constructor calls the primary one so validation is applied uniformly.

Summary
this(...) chaining is a simple but powerful way to write clean constructors, avoid code duplication and maintain consistent initialisation across different creation paths.

📌 Examples
  • class A{ A(){this(5);} A(int x){ /* main init */ } } calls A(int) from A()
  • Employee example: Employee() -> Employee(String,int,double)
  • Avoid: A(){ System.out.println(); this(5); } invalid because this() must be first
  • Chaining reduces duplicated assignments across constructors
🧮 Formulas
  1. this(args) must be the first statement in a constructor
📊 Visual ideas
Flow diagram: several constructors shown as nodes with arrows pointing to the main constructor called by this()
💻6

Calling Parent Constructor with super()

Reason for super()
When a class extends another, the child object contains the parent part. The parent class may need to perform its own initialisation; super(...) calls a specific constructor in the parent class so the parent can set its fields correctly before the child adds its own fields. This preserves correct construction order and avoids invalid parent state.

How it behaves
In a subclass constructor you can write super(arguments) as the first statement to call a parent constructor with certain parameters. If you omit super(...), the compiler inserts a call to the parent's no-argument constructor super() as long as that no-arg constructor exists. If the parent class has only parameterised constructors and no no-arg form, the subclass must explicitly call super(...) with appropriate arguments or the code will not compile.

Rules and restrictions
The super(...) call must be the first statement in the constructor body. You cannot have both this(...) and super(...) in the same constructor because both require being first. You also cannot call super(...) outside of a constructor. Calls to parent constructors chain upward: a subclass constructor calls super(...), that parent constructor may itself call its own parent via super(...), and so on until java.lang.Object is reached.

Design practice
Prefer to pass data up to the parent through super(...) rather than accessing parent fields directly, especially when those fields are private. This keeps the child class independent of parent internals and respects encapsulation. If the parent has important initialisation rules, ensure you call the correct parent constructor so those rules are applied.

Common errors
A frequent compile-time error occurs when the parent lacks a no-arg constructor: the subclass must supply an explicit super(...) call. Another mistake is placing statements before super(...). To debug constructor order problems, instrument constructors with print statements to observe the sequence in which they run.

Example
class Animal { Animal(String type) { /* init type */ } } class Dog extends Animal { Dog(String name) { super("Mammal"); this.name = name; } } Here Dog must call super(String) because Animal has no no-arg constructor.

Summary
super(...) is the mechanism that ensures parent classes initialise their part of an object before child constructors run their own setup; using it correctly is essential in inheritance.

📌 Examples
  • class A{A(int x){}} class B extends A{B(){super(5);} }
  • Dog example: Dog(String name){ super("Canine"); this.name=name; }
  • If parent has no default constructor, subclass must call super(...) explicitly
  • Cannot call super() after other statements; it must be first
🧮 Formulas
  1. super(args) must be the first statement in a constructor if used
  2. If no explicit super(...) and parent has a no-arg constructor, compiler inserts super()
📊 Visual ideas
Class hierarchy diagram with arrows: Child constructor -> calls super() -> Parent constructor runs -> Parent fields initialised -> Control returns to child constructor
💻7

Copy Constructor

Purpose
A copy constructor creates a new object by copying the state of an existing object. Java does not supply a built-in copy constructor by default, so you write one explicitly with the signature ClassName(ClassName other). A copy constructor is useful when you want a new object to start with the same data as another object but to be independent so later changes to one do not affect the other.

Shallow versus deep copy
Copies can be shallow or deep. A shallow copy copies primitive fields and object references as they are, so both original and copy share any referenced mutable objects. A deep copy duplicates not only the top-level object but also any mutable objects it references, allocating new memory and copying contents. For arrays or collection fields deep copy usually means creating new arrays or collection objects and copying their elements.

How to implement
Implement a copy constructor by allocating a new object and then copying or cloning fields appropriately. For primitives and immutable objects (like String) a direct assignment is fine. For mutable objects such as arrays or ArrayLists, create a new instance and copy elements one by one or use appropriate constructors like new ArrayList(other.list) which copies elements into a new list.

When copy is necessary
Use a copy constructor when objects represent data snapshots, when you want to avoid aliasing bugs, or when passing an object to a method that should not change the caller’s instance. Copy constructors are clearer and easier to control than the clone() mechanism at beginner level.

Common pitfalls
Forgetting to deep-copy mutable fields causes subtle bugs where changes in one object are visible in the other. Also copying complex graphs of objects can be expensive; consider whether shallow copy is acceptable and document the behaviour. Another issue is copying objects with references that should remain shared deliberately; make the choice explicit and document it.

Example
class Person { String name; int[] marks; Person(Person p) { this.name = p.name; this.marks = new int[p.marks.length]; for(int i=0;i

Summary
A well-designed copy constructor gives control over how objects are duplicated and is an important tool to avoid shared-state bugs in programmes.

📌 Examples
  • Point(Point p) { this.x = p.x; this.y = p.y; } simple copy
  • For array fields use new array and copy elements to avoid shared reference
  • Using copy: Point p2 = new Point(p1); creates p2 independent of p1
  • Shallow copy pitfall: Object with ArrayList field — copying reference causes shared list
🧮 Formulas
  1. Copy constructor signature: ClassName(ClassName other)
  2. Deep copy: allocate new mutable fields and copy contents element-by-element
📊 Visual ideas
Diagram showing original object with reference to array; copy constructor creates new object and new array with copied elements so arrays are separate
🔶8

Private Constructors and Singleton Pattern

Private constructor basics
A private constructor is a constructor declared with the private access modifier so code outside the class cannot call new to create instances. Making constructors private is a deliberate design choice when you want to restrict or control how instances of a class are created. This prevents external code from constructing objects directly and forces creation to go through controlled points inside the class.

Use cases
Common uses include utility classes that only contain static methods (such classes do not need instances) and the singleton pattern where exactly one instance of the class should ever exist. Private constructors are also used when a class provides static factory methods or a controlled pool of instances.

Simple singleton example
The basic singleton design uses a private constructor and a public static field or static method to return the one instance. For example: private static MyClass instance = new MyClass(); private MyClass() { } public static MyClass getInstance() { return instance; } This ensures only the single instance created inside the class can exist.

Alternative patterns
Singletons can be implemented with lazy initialisation where the instance is created the first time getInstance() is called. That requires care with thread safety in multi-threaded programs; at Class 10 level, the eager initialisation shown above is simpler and sufficient to understand the idea.

Advantages and disadvantages
Using private constructors and singletons centralises control and ensures single shared state when needed (for example, a logging manager). However, singletons can make testing and reuse harder since they introduce global state. Private constructors also prevent subclassing, which may be desirable or a drawback depending on design.

Practical advice
Use private constructors only when you have a clear reason: to prevent meaningless instantiation (utility classes), to enforce singleton behaviour, or to implement controlled creation through factory methods. Document the behaviour so users of the class understand why direct construction is not allowed.

Summary
Private constructors give strong control over object creation and are a fundamental tool in certain design patterns and API designs.

📌 Examples
  • class Utility { private Utility() {} public static int add(int a,int b){return a+b;} }
  • Simple singleton: class S{ private static S obj = new S(); private S(){} public static S get(){return obj;} }
  • Private constructor stops new S() outside the class
  • Private constructor prevents subclassing if all constructors are private
🧮 Formulas
  1. Private constructor signature: private ClassName() { ... }
  2. Singleton basic pattern: private static ClassName instance = new ClassName(); public static ClassName getInstance() { return instance; }
📊 Visual ideas
Diagram showing class box with private constructor, static instance inside class, and public getInstance() method returning the same instance to callers
💻9

Access Modifiers for Constructors

Overview of access levels
Constructors can be declared with the same access modifiers as methods and fields: public, protected, private, or default (package-private when no modifier is given). The chosen access level controls which code can create instances using that constructor, and therefore how widely the class may be instantiated.

Public constructors
A public constructor allows any other code to create instances. This is the common choice for classes that form part of a public API and should be usable by any caller. Public constructors are simple to understand and are appropriate when no creation restrictions are needed.

Default (package-private) constructors
If no modifier is specified the constructor is accessible only to other classes in the same package. This level of restriction is useful when you want only related classes to create instances, for example when a factory or manager in the same package should control object creation while keeping classes outside the package from instantiating them directly.

Protected constructors
A protected constructor makes sense when only subclasses or classes in the same package should be allowed to create instances. It is often used when a class is designed for extension and you want derived classes to be able to create instances but still disallow general external construction.

Private constructors
Private constructors prevent code outside the class from creating instances; they are used for singletons and utility classes as explained previously. A private constructor also prevents subclassing because a subclass cannot call a private parent constructor.

Design considerations
Choose the narrowest access that still allows required usage. If object creation should be controlled or limited, use non-public constructors and provide factory methods to create instances with the correct checks. Carefully document the intended usage so other programmers know how to instantiate the class correctly.

Common mistakes
An accidental private or package-private constructor can break client code that expects to be able to create instances. When encountering compilation errors about inaccessible constructors, check the constructor access level and whether the calling code is in a different package or is not a subclass.

Examples
public MyClass() {} // open to all; MyClass() {} // only same package; protected MyClass() {} // subclasses and package; private MyClass() {} // only inside class.

📌 Examples
  • public MyClass() {} // anyone can create
  • MyClass() {} // default: only same package
  • protected MyClass() {} // subclasses and package can use
  • private MyClass() {} // only code inside the class can create instance
📊 Visual ideas
Table-style diagram with constructor access level in one column and who can call it in another: public -> everywhere, protected -> package + subclasses, default -> package, private -> inside class only
💻10

Constructors and Inheritance Order

Execution order principle
When you create an object of a subclass, constructor execution follows an order from the top of the inheritance chain down to the bottom. First the constructors of the parent classes run in order from the highest ancestor to the immediate parent, and finally the subclass constructor runs. This sequence guarantees that the parent portion of the object is fully initialised before the child code executes.

How it happens technically
Each subclass constructor either explicitly calls a parent constructor using super(...) as its first statement or the compiler inserts an implicit call to the parent's no-argument constructor super(). That parent constructor then does its own initialisation and, if it extends another class, calls its parent in the same way. The chain continues until java.lang.Object is reached. After all parent constructors have finished, control returns down the chain so that the subclass constructor can execute.

Fields and initialisers
Instance field initialisers and instance initializer blocks in a class execute before the constructor body runs, but after the parent constructors have completed. Static initialisers are executed once when the class is loaded and are separate from constructor order. Understanding this helps avoid surprises when fields seem uninitialised inside constructors.

Why order matters
Parent constructors may allocate resources, set defaults or enforce invariants required by child classes. If a child constructor assumes those parent steps already happened, you must preserve the correct order. If the parent requires parameters, the child must call super(...) explicitly with the required arguments; otherwise compilation fails.

Debugging tips
To observe order, place print statements in each constructor. Creating a child object will show prints in parent-to-child sequence. If you see unexpected null fields, check whether the parent constructor initialised them and whether the child overwrote them incorrectly.

Practical example
Consider classes A, B extends A, and C extends B. Each constructor prints its class name. When new C() runs, the output will show A then B then C. This confirms the parent-to-child constructor execution order.

Summary
Remember: constructors execute from parent to child to ensure a stable object state; use explicit super(...) calls when needed and keep constructor logic consistent across the hierarchy.

📌 Examples
  • A -> B -> C print order when creating new C()
  • Parent fields initialised before child constructor body executes
  • If parent has required parameterised constructor, subclass must call super(args)
  • Implicit super() used only if parent has no-arg constructor
📊 Visual ideas
Stack-style diagram showing call chain: new Child() -> Child() -> super() -> Parent() -> super() ... until Object()
💻11

Common Errors with Constructors

Frequent beginner mistakes
Beginners make several repeatable errors with constructors. One very common error is writing what looks like a constructor but adding a return type (for example public void ClassName()), which makes it an ordinary method rather than a constructor. Another is forgetting parentheses when calling new, or missing matching parameter types so the chosen constructor is not found.

Default constructor surprises
Adding a parameterised constructor removes the compiler-provided default no-arg constructor. Programs that relied on the default constructor will fail to compile until a no-arg constructor is explicitly added. This is a frequent cause of confusing compile-time errors when code elsewhere calls new ClassName() without parameters.

this() and super() placement errors
A very strict rule is that both this(...) and super(...) must be the first statement in a constructor when used. Placing any other statement before them causes a compile-time error. Also you cannot use both in a single constructor because only one can be first. Another common mistake is attempting to use this(...) to call a parent constructor; this calls constructors only in the same class.

Copy and aliasing bugs
When copying objects, students sometimes copy references to mutable fields instead of creating new copies. This leads to aliasing where changes to one object unexpectedly affect the other. The remedy is to perform a deep copy of mutable fields such as arrays and lists inside the copy constructor.

Access level issues
Using private constructors unintentionally blocks code that should create objects. If tests or other classes in different packages cannot instantiate a class, check the constructor access modifier. Conversely, making constructors too open can allow incorrect usage.

Diagnosis and fixes
Read compiler error messages: they often point to missing constructors or inaccessible ones. Add explicit constructors as needed, correct misplaced return types, and ensure this(...) or super(...) are placed first. For copy problems test by modifying the original after copying to see whether the copy changes.

Practical checklist
For each class: confirm constructor names match the class, remove any return types, verify parentheses and parameter types, ensure needed no-arg constructor exists if called elsewhere, and check that mutable fields are copied when required.

📌 Examples
  • Mistake: public void Student() { } // not a constructor
  • Error: calling new C() fails because only C(int) exists and no C()
  • Invalid: { System.out.println(); super(); } // super must be first
  • Copy bug: copying an array reference instead of new array
📊 Visual ideas
List-style visual of common errors with causes and fixes aligned side-by-side
💻12

Constructors and Encapsulation

Role in encapsulation
Encapsulation means keeping an object's internal state hidden and providing controlled access through methods. Constructors are essential to encapsulation because they determine how an object's private fields are set initially. By validating and setting fields inside constructors, you prevent code from creating objects in invalid states.

Initialisation and validation
Use constructors to check input values and enforce invariants. For example, if a BankAccount must not have a negative balance, check the provided initial balance in the constructor and either correct it or throw an exception. This guarantees that once construction finishes, the object satisfies its required conditions.

Immutable objects
One strong way to use constructors and encapsulation is to create immutable classes: declare fields private and final, set them only in constructors, and provide no setters. Immutable objects are simpler to reason about, thread-safe by design, and less error-prone. Constructors become the single place where state is set.

Handling mutable inputs
When constructors accept arrays or collections as parameters, prefer copying them into private fields rather than storing the caller’s reference. Returning a copy from getters preserves encapsulation. For example, if a constructor receives an int[] marks array, allocate a new array and copy elements so later changes by the caller do not alter the object.

Factory methods and private constructors
Sometimes you want to prevent direct construction while still offering controlled creation paths; make constructors private and provide public static factory methods. This allows validation, caching or returning special instances while keeping internal details hidden from callers.

Documentation and clarity
Always document what each constructor expects and whether it copies inputs or keeps references. This avoids surprises for users of your class and keeps encapsulation robust across different parts of a program.

Summary
Correct use of constructors is a foundational technique for maintaining encapsulation and producing robust classes that are easy to use and less likely to produce bugs due to invalid initial state.

📌 Examples
  • Immutable Point: private final int x,y; public Point(int x,int y){this.x=x;this.y=y;} no setters
  • Validate in constructor: if(age<0) throw new IllegalArgumentException("age");
  • Use getters that return copies for array fields to preserve encapsulation
  • Factory method example: public static Date fromYMD(int y,int m,int d) { return new Date(y,m,d); } with private constructor
📊 Visual ideas
Diagram showing class with private fields initialised by constructor; public getters provide controlled access
💻13

Constructors in Java vs Methods

Key differences
Although constructors resemble methods in syntax, they differ in important ways. A constructor's name must exactly match the class name and it has no return type. Methods may have any name and must declare a return type. A constructor is used only once at the moment the object is created; methods are invoked repeatedly on existing objects and may return values.

Inheritance and constructors
Constructors are not inherited. Each class must provide its own constructors, possibly calling a parent constructor via super(...). Methods, on the other hand, can be inherited and overridden. This difference explains why subclasses must explicitly call parent constructors if the parent needs certain initialisation data.

Static context
Methods can be static and run without creating an object; constructors are always about creating instances. If a class only offers static behaviour and no instances are needed, giving the class a private constructor prevents accidental instantiation and makes the static nature clear.

When to use each
Use constructors only for initialisation tasks that prepare the object for valid use. Use methods for behaviour, calculations, or state changes that occur after the object exists. For example, use a constructor to set an account balance at creation and use deposit and withdraw methods to change it later.

Overloading and signatures
Both constructors and methods can be overloaded, but constructors are selected only during object creation via new. Unlike methods which may be overloaded for different return types or generic variations, constructors must differ in parameter lists and cannot be distinguished by return type since constructors have none.

Common student errors
A frequent mistake is writing a method that looks like a constructor by naming it the class name but giving it a return type; this becomes a normal method and the intended constructor does not exist. Always omit the return type when writing a constructor.

Summary
Remember: constructors build objects; methods provide behaviour. Keeping this distinction clear aids correct class design and prevents many common errors.

📌 Examples
  • Constructor: public Car(String m){ this.model=m; } // initialises
  • Method: public void drive() { /* behaviour */ } // action after creation
  • Cannot write: public int Car() { return 0; } because constructors have no return type
  • Overloaded methods and constructors both exist but serve different roles
📊 Visual ideas
Comparison table diagram: Constructors vs Methods with characteristics listed for each column
💻14

Using Constructors with Arrays and Collections

Initialising complex fields
Many classes contain arrays or collection objects as fields. Constructors are the appropriate place to allocate and initialise these fields so the object is ready to use. A constructor should decide whether to accept an existing array or collection reference from the caller, or to create its own.

Avoid sharing mutable objects
If the constructor simply assigns the passed array or collection reference to a field, the caller and the object will share the same mutable data. This can lead to unexpected changes and hard-to-find bugs. To avoid this, most constructors should copy the incoming data into newly allocated arrays or collections.

How to copy safely
For arrays, allocate a new array of the same length and copy elements in a loop. For collections like ArrayList, you can use new ArrayList(existingList) which copies elements into a fresh list. When the elements themselves are mutable objects, decide whether to perform deep copies of those elements as well or to document that element sharing is intentional.

Initialise empty instead of null
A good practice is to ensure collection fields are never null. If no data is provided, initialise the field to an empty collection in the constructor. This eliminates repeated null checks in other methods and simplifies usage.

Performance and design trade-offs
Copying improves safety but costs time and memory. For very large datasets, document whether copying occurs and consider alternatives such as unmodifiable wrappers or views when appropriate. At Class 10 level, default to copying for encapsulation unless performance is explicitly important.

Examples and patterns
class Scores { private int[] marks; Scores(int[] m) { marks = new int[m.length]; for(int i=0;i

Summary
Constructors should prepare array and collection fields carefully: copy mutable inputs, avoid null fields by initialising to empty structures, and document whether deep copy is performed when necessary.

📌 Examples
  • Copy array in constructor to avoid external modification
  • Use new ArrayList(existing) to copy a collection
  • Initialise to empty collection: this.items = new ArrayList();
  • Avoid null collections by defaulting to empty list
📊 Visual ideas
Diagram showing external array passed to constructor, constructor creates new array and copies elements so internal array is separate
💻15

Testing, Exercises and Revision

Why test constructors?
Constructors are the first code executed when creating objects, so errors in constructors create objects in invalid states and cause bugs later. Testing constructors ensures objects start in the correct state, validation rules work, and inheritance chains initialise in the expected order.

Simple testing approaches
At Class 10 level, simple main methods and small driver programs are the most practical tests. For each constructor variant, write a small snippet that creates an object and prints its fields through getters. Test normal and edge cases: empty strings, negative numbers where not allowed, null values where applicable, and very large numbers. For copy constructors, create a copy, modify the original and verify the copy does not change if a deep copy was intended.

Tracing execution order
To verify constructor chaining and inheritance order, insert System.out.println statements at the start of each constructor. Creating an object will produce output showing the parent constructors executing first, then the child. This simple trace helps students visualise the flow and confirm proper use of this() and super().

Practical exercises
Try the following small programs: (1) Book class with default, parameterised and copy constructors, and methods to display details; (2) Student class that accepts an array of marks and copies it inside the constructor, plus a method to compute average; (3) Shape hierarchy where Shape has colour and constructors, and Rectangle and Circle call super() and compute area. These exercises combine constructor concepts with arrays, copying and inheritance.

Revision checklist
Remember rules: constructor name equals class name; constructors have no return type; this(...) and super(...) must be the first statement if used; the compiler provides a default no-arg constructor only if no constructors are declared; private constructors restrict instantiation. Best practices include keeping constructors short, validating inputs, copying mutable inputs, and using constructor chaining to centralise initialisation.

Exam preparation tips
ICSE questions ask for short programs, output tracing and identifying errors. Practice writing small classes with multiple constructors, tracing outputs, and fixing common mistakes like incorrect return types or misplaced super()/this(). Use comments to explain why a constructor is chosen in each example and be ready to explain shallow vs deep copy in a couple of sentences.

Final note
Mastery of testing, practice and remembering the key rules turns constructors from a source of errors into a reliable tool for building correct object-oriented programs.

📌 Examples
  • Write a main method to create objects with all constructor variants and print field values
  • Trace prints: Parent constructor then Child constructor to confirm order
  • Test negative inputs to ensure constructor validation works
  • Test copy constructor by modifying original and verifying copy does not change
🧮 Formulas
  1. Constructor rules summary: name = class name; no return type; this(...) or super(...) must be first when used
📊 Visual ideas
Flow diagram representing test steps: create object -> check fields -> assert expected values -> report pass/fail

Key Concepts

Constructor
A special block in a class that initialises new objects and has the same name as the class with no return type.
Default constructor
A no-argument constructor provided by the compiler when no constructors are written by the programmer.
Parameterised constructor
A constructor that accepts arguments to set initial field values when an object is created.
Constructor overloading
Having multiple constructors in the same class with different parameter lists.
Constructor chaining
Calling one constructor from another in the same class using this(...) to reuse initialisation code.
super()
A call used in a subclass constructor to invoke a parent class constructor.
Copy constructor
A constructor that creates a new object by copying the fields of an existing object.
Shallow copy
Copying field values including references so that mutable referenced objects are shared.
Deep copy
Creating new copies of mutable referenced objects so the new object is independent of the original.
Access modifiers
Keywords (public, protected, private, default) that control who can call a constructor.
Private constructor
A constructor not accessible outside the class, used to prevent external instantiation.
Immutable object
An object whose state cannot be changed after construction, often using final fields and no setters.
No-arg constructor
A constructor that takes no parameters and initialises an object to default values.
Validation in constructor
Checking and enforcing correct input values inside a constructor to maintain object invariants.
this
A reference to the current object; used in constructors to disambiguate fields and call other constructors.

Practice Questions

  1. What is a constructor and how does it differ from a method? / एक कन्स्ट्रक्टर क्या है और यह एक मेथड से कैसे अलग है?
    Show answer

    A constructor is a special block in a class used to initialise new objects; it has the same name as the class and no return type, and it runs automatically when an object is created. A method can have any name, must declare a return type (or void), and is called explicitly on an object. / कन्स्ट्रक्टर एक क्लास का विशेष ब्लॉक है जो नए ऑब्जेक्ट्स को प्रारंभ करता है; इसका नाम क्लास के जैसा होता है और इसमें कोई रिटर्न टाइप नहीं होता है, और यह ऑब्जेक्ट बनते समय स्वतः चलता है। एक मेथड किसी भी नाम का हो सकता है, उसे रिटर्न टाइप (या void) चाहिए और उसे निश्चित रूप से कॉल करना होता है।

  2. When does the Java compiler provide a default constructor? Give an example. / जावा कंपाइलर कब डिफ़ॉल्ट कन्स्ट्रक्टर देता है? एक उदाहरण दें।
    Show answer

    The compiler provides a default no-argument constructor only when the programmer writes no constructors in the class. Example: class A { int x; } // compiler supplies A(). / कंपाइलर केवल तब डिफ़ॉल्ट no-arg कन्स्ट्रक्टर देता है जब प्रोग्रामर क्लास में कोई कन्स्ट्रक्टर नहीं लिखता। उदाहरण: class A { int x; } // कंपाइलर A() जोड़ता है।

  3. Write a parameterised constructor for a class Point with fields x and y and show how to create an object with x=3 and y=4. / x और y फील्ड वाली Point क्लास के लिए एक पैरामीटराइज़्ड कन्स्ट्रक्टर लिखिए और दिखाइए कि x=3 और y=4 वाला ऑब्जेक्ट कैसे बनाएँ।
    Show answer

    Constructor: public Point(int x, int y) { this.x = x; this.y = y; } Creating object: Point p = new Point(3, 4); / कन्स्ट्रक्टर: public Point(int x, int y) { this.x = x; this.y = y; } ऑब्जेक्ट बनाना: Point p = new Point(3, 4);

  4. Explain constructor chaining using this() with a short code pattern. / this() का उपयोग करके कन्स्ट्रक्टर चैनिंग समझाइए और एक छोटा कोड पैटर्न दें।
    Show answer

    Constructor chaining calls one constructor from another to reuse code. Example pattern: public ClassA() { this("default"); } public ClassA(String s) { this.field = s; } The no-arg constructor calls the parameterised one using this(...). / कन्स्ट्रक्टर चैनिंग एक कन्स्ट्रक्टर से दूसरे को कॉल करके कोड दोहराव घटाती है। उदाहरण: public ClassA() { this("default"); } public ClassA(String s) { this.field = s; } यहाँ no-arg कन्स्ट्रक्टर this(...) से parameterised कन्स्ट्रक्टर को कॉल करता है।

  5. What happens if a parent class has only a parameterised constructor and the child constructor does not call super(...) explicitly? / यदि पैरेंट क्लास के पास केवल पैरामीटराइज़्ड कन्स्ट्रक्टर है और चाइल्ड कन्स्ट्रक्टर super(...) स्पष्ट रूप से नहीं बुलाता, तो क्या होगा?
    Show answer

    If parent has no no-arg constructor, and the child constructor does not explicitly call super(...), the compiler attempts to insert super() and fails, causing a compile-time error. The child must call an appropriate super(...) with arguments. / यदि पैरेंट के पास no-arg कन्स्ट्रक्टर नहीं है और चाइल्ड कन्स्ट्रक्टर super(...) स्पष्ट रूप से नहीं बुलाता, तो कंपाइलर super() डालने की कोशिश करेगा और असफल होगा, जिससे कंपाइल-टाइम त्रुटि आएगी। चाइल्ड को उपयुक्त super(...) कॉल करनी चाहिए।

  6. Define a copy constructor and explain difference between shallow and deep copy with an example. / एक कॉपी कन्स्ट्रक्टर परिभाषित कीजिए और शैलो तथा डीप कॉपी में अंतर एक उदाहरण के साथ समझाइए।
    Show answer

    A copy constructor builds a new object using the data of an existing object, signature ClassName(ClassName other). Shallow copy copies references so mutable fields are shared; deep copy allocates new mutable objects and copies their contents. Example: shallow: this.arr = other.arr; deep: this.arr = new int[other.arr.length]; copy elements in a loop. / कॉपी कन्स्ट्रक्टर एक मौजूदा ऑब्जेक्ट के डेटा से नया ऑब्जेक्ट बनाता है, सिग्नेचर ClassName(ClassName other)। शैलो कॉपी संदर्भ कॉपी करती है इसलिए म्यूटेबल फील्ड साझा होते हैं; डीप कॉपी नए म्यूटेबल ऑब्जेक्ट बनाकर उनके कंटेंट कॉपी करती है। उदाहरण: शैलो: this.arr = other.arr; डीप: this.arr = new int[other.arr.length]; और लूप में तत्व कॉपी करें।

  7. Give two reasons to make a constructor private. / कन्स्ट्रक्टर को प्राइवेट करने के दो कारण बताइए।
    Show answer

    Reasons: (1) To prevent external code from creating instances (used in singleton or utility classes). (2) To control creation through static factory methods or to restrict subclassing. / कारण: (1) बाहरी कोड को ऑब्जेक्ट बनाने से रोकना (singleton या utility क्लास में)। (2) static factory methods के माध्यम से निर्माण नियंत्रित करने के लिए या subclassing सीमित करने के लिए।

  8. Spot the error: public class Test { public void Test() { System.out.println("Hello"); } } / त्रुटि खोजिए: public class Test { public void Test() { System.out.println("Hello"); } }
    Show answer

    This is a method, not a constructor, because it has a return type void. The class has no constructor, so compiler supplies a default no-arg constructor. To make it a constructor remove void: public Test() { ... } / यह मेथड है, कन्स्ट्रक्टर नहीं क्योंकि इसमें void है। क्लास के पास कोई कन्स्ट्रक्टर नहीं है इसलिए कंपाइलर default no-arg कन्स्ट्रक्टर देगा। इसे कन्स्ट्रक्टर बनाने के लिए void हटाएँ: public Test() { ... }

  9. Write a short program outline for a Student class that uses a constructor to copy an input marks array. / एक छोटा प्रोग्राम रूपरेखा लिखिए जिसमें Student क्लास एक कन्स्ट्रक्टर का उपयोग कर इनपुट marks एरे की कॉपी बनाता है।
    Show answer

    Outline: class Student { private int[] marks; Student(int[] m) { marks = new int[m.length]; for(int i=0;i<m.length;i++) marks[i]=m[i]; } // getter returns copy or computed average } This copies the passed array to avoid sharing. / रूपरेखा: class Student { private int[] marks; Student(int[] m) { marks = new int[m.length]; for(int i=0;i<m.length;i++) marks[i]=m[i]; } // getter कॉपी लौटाए या औसत निकाले } यह पास किया गया एरे कॉपी करता है ताकि साझा न हो।

  10. How would you test the order of constructor execution in a three-level inheritance chain? / तीन-स्तरीय इनहेरिटेंस चेन में कन्स्ट्रक्टर निष्पादन के क्रम का परीक्षण आप कैसे करेंगे?
    Show answer

    Insert print statements in each constructor starting from top parent to lowest child. Create a child object and observe printed order; it should show parent constructors first down to child. Example prints: System.out.println("Parent"); System.out.println("Child"); / प्रत्येक कन्स्ट्रक्टर में प्रिंट स्टेटमेंट डालें—ऊपर से नीचे—और चाइल्ड ऑब्जेक्ट बनाइए। प्रिंट से क्रम दिखाई देगा; यह पैरेंट से शुरू होकर चाइल्ड तक होगा। उदाहरण: System.out.println("Parent"); System.out.println("Child");

Related Laws & Principles

Explore all

Foundational laws & principles connected to this chapter — tap to open in the Laws Explorer.

Loading related laws…
Sourced from 0 content files · LLOS Learn · browse all chapters