A constructor initializes a new object and can reject inputs that would leave it unusable.
Java constructors and validated state
Working model
Require the identifier at creation. The constructor below validates the supplied value before storing it. This keeps every successfully created ticket usable without a later initialize call.
Code
public class SupportTicket {
private final String ticketId;
public SupportTicket(String ticketId) {
if (ticketId == null || ticketId.trim().isEmpty()) {
throw new IllegalArgumentException("ticketId is required");
}
this.ticketId = ticketId;
}
public String id() {
return ticketId;
}
}A constructor has the class name and no return type. this.ticketId distinguishes the field from the parameter. final prevents reassignment of this field after construction; it does not make every object referenced by a final field immutable.
Cost and design choices
Validation adds work once per creation. That is often cheaper than requiring every operation to recover from missing state. Keep expensive I/O out of constructors when failures need a separate retry policy.
Keep partially built objects private
Do not publish this to another thread or callback before construction finishes. The observer can see an object whose invariants have not been established. Calling an overridable method from a constructor can also dispatch to subclass code before subclass initialization completes.
Validate related fields together. Two fields can each be individually valid while their combination is invalid, such as an end timestamp before a start timestamp. Constructor success should mean the complete object state is usable.
Connected lessons
Continue with Java encapsulation and object ownership, Java Tutorial.
Common Mistakes
Adding a return type turns the declaration into a method. Do not call overridable methods from constructors: subclass state may not yet be initialized. Avoid storing mutable input collections without deciding who owns later edits.
