1.13 Object Creation
Creating and Initializing Objects: Constructors
A Java class serves as a blueprint for creating objects, defining both their state (attributes or instance variables) and behavior (methods). Central to the creation of these objects are constructors, specialized methods like World() and Turtle(habitat). Their primary role is to initialize the attributes of a newly created object to a valid state immediately after memory has been allocated for it.
When a new object is required, the new keyword is used, followed by the class name and parentheses, potentially containing arguments (new ClassName()). The execution of this statement involves two crucial steps:
Memory Allocation: The Java Virtual Machine (JVM) allocates a block of memory on the heap for the new object, sufficient to store all its instance variables.
Constructor Invocation: Immediately after memory allocation, the specified constructor of the class is called. This constructor performs the necessary initialization tasks, setting initial values for the object's attributes. For example,
new World()creates a newWorldobject and calls its no-argument constructor, whilenew Turtle(habitat)creates a newTurtleobject and initializes it within the providedhabitatreference.
// General syntax for object creation and initialization:
// ClassName variableName = new ClassName(parameters);
// Example 1: Creating a World object
World habitat = new World(); // Creates a new World object using the no-argument constructor.
// 'habitat' is an object variable holding a reference to this new World instance.
// Example 2: Creating a Turtle object within the 'habitat'
Turtle t = new Turtle(habitat); // Creates a new Turtle object, passing the 'habitat' reference
// as an argument to its constructor for initialization.Overloading Constructors
A class can define multiple constructors, a concept known as constructor overloading. This allows objects of the same class to be initialized in different ways, depending on the number, type, and order of parameters provided during instantiation. Java distinguishes between overloaded constructors based on their signature (the constructor's name combined with the number and types of its parameters).
No-argument constructor: This is a constructor that has no parameters within the parentheses, such as
World(). It's often used to initialize an object's attributes to default values. If no constructor is explicitly defined in a class, Java provides a default public no-argument constructor implicitly, provided no other constructors are defined.Parameterized Constructors: These constructors take one or more parameters, like
Turtle(habitat)orWorld(int width, int height). A parameter (also referred to as an actual parameter or argument when passed during the call) is a value supplied to the constructor at the time of object creation. These values are used to customize the initial state of the object's attributes.
The World class commonly illustrates constructor overloading with at least two constructors:
A no-argument constructor:
World()initializes a world with default dimensions (e.g., 400Ă—400 pixels).A parameterized constructor:
World(int width, int height)allows the user to specify custom dimensions for the world when it's created.

Object Variables and References
An object variable, such as Turtle t1, does not directly store the object itself. Instead, it holds a reference to an object. A reference is essentially a memory address or a pointer that indicates where the actual object data is stored in the computer's memory (specifically, on the heap). It acts like a tracking number, allowing the program to locate and interact with the object.
Object variables can also be initialized to null (e.g., Turtle t1 = null;). When an object variable is null, it signifies that it currently does not refer to any object in memory. Attempting to call a method or access an attribute on a null reference will result in a NullPointerException at runtime, as there is no object to perform the operation on. To become useful, a null object variable must first be assigned a reference to an actual object, typically by using the new keyword to create a new object or by assigning it the reference held by another existing object variable.