CSUN COMP 110/L Practice Set: Classes and Objects
Fundamentals
Focus Topic: Class Definition, Object Instantiation, and Relationships
This extensive practice set is designed to test your mastery of the foundational
concepts of Object-Oriented Programming (OOP) in the context of COMP 110/L. You
will define classes, manage object state (attributes), implement behavior (methods),
and analyze the core relationship between the class blueprint and its instantiated
objects.
Part I: Conceptual Analysis and Terminology
These exercises ensure you have a precise understanding of the foundational
vocabulary and principles of OOP.
Exercise 1: Class vs. Object — The Blueprint and the Instance
The relationship between a class and an object is fundamental to OOP. A class is the
conceptual blueprint, while an object is a concrete, tangible instance of that
blueprint.
Task A: Detailed Differentiation
Provide a detailed comparison of a Class and an Object using a real-world analogy
(e.g., a cookie cutter and a cookie, or a car design plan and a physical car). Your
explanation must address the following points for both concepts:
Memory Allocation: When is memory allocated for each?
Existence: Can you interact with a class without creating an object?
Mutuality (State): Does a class possess attributes that can change over time, or is
that property exclusive to the object?
Task B: Instantiation in Action
Write the specific Java syntax required to define a class named Textbook and then
create three distinct objects (instances) of that class: comp110Text, math150Text,
and geology101Text. Explain what happens in memory when the new keyword is
executed during the creation of the math150Text object.
Task C: Association and Aggregation Introduction
Briefly define the two primary types of "has-a" relationships that exist between
classes (known as composition/aggregation and association). Why is understanding
these relationships crucial when designing the attributes (instance variables) of a
class?
Exercise 2: Attributes and Methods — State vs. Behavior
The primary components of a class are its attributes (data/state) and its methods
(actions/behavior).
Task A: Defining Attributes and Scope
Assume you are designing a class named StudentEnrollment to track a single
students academic profile. List three essential attributes this class must have and
specify the most appropriate data type and access modifier (e.g., private, public) for
each. Justify your choice of access modifier based on the principle of encapsulation.
Attribute 1:
Data Type:
Access Modifier:
Justification:
Attribute 2:
Data Type:
Access Modifier:
Justification:
Attribute 3:
Data Type:
Access Modifier:
Justification:
Task B: Methods and Functionality
Continuing with the StudentEnrollment class, propose two distinct methods that the
class should contain. For each method, define its purpose, its full signature
(including return type and parameters), and explain why it must be an instance
method (non-static) rather than a class method (static).
Method 1:
Purpose:
Signature:
Justification (Instance vs. Static):
Method 2:
Purpose:
Signature:
Justification (Instance vs. Static):
Task C: Constructors Role
Explain the specific purpose of a constructor in Java OOP. Contrast the default
constructor (if one exists) with a parameterized constructor. When initializing the
StudentEnrollment object, why is it considered best practice to use a parameterized
constructor to set initial attribute values, rather than relying on default values or
using setter methods immediately after instantiation?
Exercise 3: Encapsulation and Data Hiding
Encapsulation is one of the four pillars of OOP and relies heavily on controlling
access to attributes.
Task A: The Need for Getters and Setters
Explain in detail why, if all instance variables (attributes) are declared private, we
must provide public accessor (getter) and mutator (setter) methods to interact with
them from outside the class. Describe a scenario where a setter method would
include input validation logic to protect the integrity of an objects state (e.g.,
ensuring a grade attribute is between 0 and 4.0).
Task B: The this Keyword
Explain the two primary uses of the this keyword within the context of a class
definition in Java. Provide a brief code snippet illustrating its use to resolve a
potential naming ambiguity when defining a parameterized constructor.
Task C: Analyzing Code Structure (Debugging)
Analyze the following Java class definition. Identify one significant OOP principle
violation and one syntactical flaw related to method definition or access. Provide the
corrected code structure.
Flawed Class Snippet:
public class LibraryBook {
public String title;private int dueDate;public void
setTitle(String newTitle) { title = newTitle;}private int
getDueDate() { return dueDate;}
}
OOP Principle Violation:
Syntactical Flaw:
Correction (Getter/Setter):
Part II: Implementation and Design (Class Construction)
These exercises require you to apply the principles from Part I to design and write
the structure of complete classes.
Exercise 4: Designing a Vehicle Class
You are tasked with designing a basic Vehicle class for a transportation simulation.
Task A: Class Structure Definition
Define the Vehicle class with the following specifications:
Attributes:
private String make
private String model
private double fuelLevel (representing the percentage of fuel, 0.0 to 1.0)
Constructor: A parameterized constructor that accepts make, model, and an initial
fuelLevel.
Accessor (Getter) Methods: Public methods for all three attributes (getMake(),
getModel(), getFuelLevel()).
Mutator (Setter) Methods:
public void setFuelLevel(double level): This method must include validation to
ensure the level is between 0.0 and 1.0 (inclusive). If the input is invalid, it should
print an error message and not update the attribute.
Task B: Behavior Implementation (Method)
Implement the following instance method:
public double drive(int miles):
This method simulates driving. Assume the vehicle consumes 0.01 units of fuel per
mile.
It should calculate the maximum distance the vehicle can travel based on its current
fuelLevel (Max Distance = fuelLevel / 0.01).
If miles is greater than the Max Distance, the vehicle runs out of fuel. In this case,
update fuelLevel to 0.0 and return the actual miles driven (which is the Max
Distance).
If miles is less than or equal to the Max Distance, update fuelLevel by subtracting the
fuel consumed (miles * 0.01) and return the input miles.
Exercise 5: Object Interaction and Method Chaining
Objects rarely exist in isolation; they interact with each other by calling methods.
Task A: Instantiation and Initial State
Write the Java code to create two Vehicle objects using the class defined in Exercise
4. Assume the Vehicle class has been compiled and is accessible.
car1: Make "Toyota", Model "Prius", Fuel 0.85
car2: Make "Ford", Model "F150", Fuel 0.50
Task B: Method Chaining and State Change
Write a sequence of commands to perform the following interactions, using the
objects created in Task A. Show the output or the resulting attribute value after each
step.
car1 drives 50 miles. What is the new fuelLevel?
Attempt to set car2s fuel level to 1.5. What is the printed output and the resulting
fuelLevel?
car2 attempts to drive 60 miles. What is the actual distance driven and the final
fuelLevel?
Task C: Design for Inter-Object Behavior
If you needed to implement a method transferFuel(Vehicle recipient, double
amount) within the Vehicle class, which would decrease the current vehicles fuel
and increase the recipients fuel, explain why the recipient object must be passed as
a parameter to the method. Write the signature for this method.
Exercise 6: Static vs. Instance Members
Understanding when to use static (class-level) members versus instance (object-
level) members is essential for efficient OOP design.
Task A: Designing the University Class
Design a simple University class to manage general data about a single campus.
Specify and justify the access modifier and the static/instance nature of the
following members:
Campus Name: (e.g., "California State University, Northridge")
Current Enrollment: (The total number of students currently registered)
increaseEnrollment() Method: (A method to increment the current enrollment
count)
getCampusName() Method: (A method to retrieve the campus name)
Use the following format for justification:
Member
Nature
(Static/Instance)
Access
(Private/Public) Justification
. Campus Name
2. Current Enrollment
3.
increaseEnrollment()
4. getCampusName()
Note: Convert the above table structure into a formatted list structure as required.
Task B: Static Initialization
Explain how you would initialize a private static final attribute (like a fixed
maximum student capacity) in the University class. Why must this type of attribute
be defined and initialized immediately, and why can it not be changed later by an
instance method?
Task C: The Static Utility Case
Provide an example of a common Java class or method (from the standard library)
that is exclusively static (a class method) and explain why it is structured that way.
Why does this utility method not require an object instance to be created before it is
called?
Part III: Reference Variables and Memory Allocation
These exercises focus on how objects are stored in memory and how reference
variables interact with them.
Exercise 7: References and the Heap
In Java, object variables do not hold the object itself, but rather a reference (memory
address) to the object residing in the heap memory.
Task A: Heap vs. Stack
Explain the difference between the Stack and the Heap memory regions in the
context of object creation. Specifically, what is stored on the Stack when you execute
the line Vehicle myCar = new Vehicle("Tesla", "Model Y", 1.0); and what is stored on
the Heap?
Task B: Multiple References and Aliasing
Consider the following sequence of Java code, assuming the Vehicle class is
available:
Vehicle v1 = new Vehicle("A", "Model 1", 0.5);
Vehicle v2 = new Vehicle("B", "Model 2", 0.8);
Vehicle v3 = v1;
v1.setFuelLevel(0.95);
Analyze the code and answer the following questions:
How many Vehicle objects exist in memory after these lines execute?
What is the value of v3.getFuelLevel() after the last line executes?
If the line v2 = v1; were added next, and then v2.setFuelLevel(0.1); was executed,
what would be the value of v3.getFuelLevel()? Explain the concept of aliasing that
makes this happen.
Exercise 8: Passing Objects to Methods (Call by Value)
When an object is passed as an argument to a method, it is still passed by value (a
copy of the reference is passed).
Task A: Method Parameter Scope
Write a simple Java method signature modifyVehicle(Vehicle car) that takes a
Vehicle object as a parameter. Inside this method, if you were to write the line car =
new Vehicle("New Make", "New Model", 0.0);, would the original object passed into
the method be changed (i.e., would its make/model be replaced)? Explain your
reasoning based on the "pass by value" mechanism for references.
Task B: Modifying Attributes via Reference
Continuing from Task A, if instead of creating a new object, you execute
car.setFuelLevel(0.0); inside the modifyVehicle method, would the original object
passed into the method be changed? Why or why not? Differentiate this action from
the operation described in Task A.
Exercise 9: Garbage Collection and Object Lifecycle
Objects created on the heap do not exist forever; they are subject to garbage
collection.
Task A: Object Lifetime
Explain what criteria an object must meet in Java for it to become eligible for
Garbage Collection (GC). When does the GC mechanism typically run?
Task B: Object Destruction (Conceptual)
In C++ or other languages, the programmer must explicitly delete objects. In Java,
this is handled automatically. Describe the conceptual flow of an objects life cycle
from its initial creation (new) to the moment it is physically removed from the heap.
Task C: Scope and Reference Loss
Consider the following code block within a main method:
public static void main(String[] args) {
{ // Start of Inner Scope Vehicle truck = new Vehicle("GMC",
"Sierra", 0.75); // ... some operations on truck} // End of
Inner Scope// Can truck be accessed here?
}
Explain what happens to the truck reference variable and the Vehicle object it points
to when the execution reaches the "End of Inner Scope" line. When does the object
become eligible for garbage collection?
Part IV: Detailed Solutions and Explanations
Solution 1: Class vs. Object
Task A: Detailed Differentiation
We can use the analogy of a Digital Camera Specification (Class) and a Photo taken
by that camera (Object).
Feature
Class (Camera Specification)
Object (The Photo Itself)
Concept
A blueprint, template, or design. It defines what attributes and methods the entity
will have.
A concrete, real-world instance of the blueprint.
Memory Allocation
Memory is allocated only for the class definition itself, primarily in the Method Area,
when the program loads the class file. No memory is allocated for instance data.
Memory is allocated in the Heap specifically for the objects instance variables
(attributes) when the new keyword is used.
Existence
Yes, you can access static members or load the class definition, but you cannot
perform actions that depend on instance variables.
No, the object cannot exist without its defining class.
Mutability (State)
A class does not have "state" in the sense of attribute values. It only defines the
structure of the state.
An object holds the specific, mutable state (attribute values) defined by the class.
Each object has its own unique set of values.
Task B: Instantiation in Action (Java Syntax)
Class Definition:
public class Textbook {
// Attributes and methods go here
}
Object Creation/Instantiation:
Textbook comp110Text = new Textbook();
Textbook math150Text = new Textbook();
Textbook geology101Text = new Textbook();
Memory Explanation (new keyword):
When new Textbook() is executed for the math150Text object:
Memory Allocation: The Java Virtual Machine (JVM) allocates a block of memory in
the Heap large enough to store all the instance variables (attributes) defined in the
Textbook class (e.g., title, author, ISBN).
Initialization: The allocated memory space is initialized. Numerical attributes are set
to 0, booleans to false, and reference types (like Strings) are set to null.
Constructor Call: The Textbook() constructor is executed, which can further
customize the initial state of the object.
Reference Return: A memory address (reference) pointing to this newly created
object in the Heap is returned. This reference is then stored in the Stack variable,
math150Text.
Task C: Association and Aggregation Introduction
Both Association and Aggregation/Composition describe a "has-a" relationship,
meaning one class includes an object of another class as one of its attributes.
Association (General "has-a" relationship): A loose relationship where objects can
exist independently. (e.g., A Student is associated with a Professor).
Composition/Aggregation (Strong "has-a" relationship): A tight relationship where
one object is an essential part of another and usually cannot exist without it. (e.g., A
Car is composed of an Engine).
Cruciality to Attribute Design:
Understanding these relationships is crucial because it dictates the data type of the
classs attributes. If a StudentEnrollment class needs to know the students primary
computer science instructor, the class wont store the instructors name as a simple
String; it will store the entire Professor object as an attribute:
private Professor csInstructor; // This attribute establishes the association
relationship.
This makes the StudentEnrollment object richer, allowing it to interact with the
Professor objects methods (e.g., calling csInstructor.sendEmail()).
Solution 2: Attributes and Methods
Task A: Defining Attributes and Scope
The principle of Encapsulation dictates that data (attributes) should be hidden from
direct external manipulation to protect the integrity of the objects state. This is
achieved by using the private access modifier.
Attribute 1: studentID
Data Type: String (Handles leading zeros/non-numeric IDs common in universities)
Access Modifier: private
Justification: The student ID is unique and should ideally be read-only or set only
upon creation. Marking it private prevents external classes from accidentally
changing this fundamental identifier, protecting data integrity.
Attribute 2: currentGPA
Data Type: double
Access Modifier: private
Justification: The GPA must be calculated or set using validation logic (e.g., ensuring
its between 0.0 and 4.0). Making it private forces external access through a public
setter method, where this crucial validation can be enforced, thus maintaining a
consistent and valid state.
Attribute 3: enrolledCourses
Data Type: ArrayList (or ArrayList)
Access Modifier: private
Justification: This structure can change frequently (add/drop courses). Hiding the
list itself prevents external users from clearing or manipulating the internal list
structure arbitrarily. Instead, specialized public methods (like addCourse()) should
control access, ensuring rules (like credit limits) are followed.
Task B: Methods and Functionality
Both proposed methods rely on the specific state (currentGPA or enrolledCourses)
of a single student object, making them non-static (instance methods).
Method 1: calculateSemesterGPA
Purpose: Calculates and updates the currentGPA attribute based on a list of new
course grades provided at the end of a semester.
Signature: public void calculateSemesterGPA(ArrayList grades, ArrayList credits)
Justification (Instance vs. Static): This method modifies the state (currentGPA) of
the specific StudentEnrollment object it is called upon. A static method cannot
access or change instance-specific variables, so this must be an instance method.
Method 2: isEligibleForHonors
Purpose: Determines if the students currentGPA meets the universitys threshold for
honors status (e.g., 3.5 or higher).
Signature: public boolean isEligibleForHonors()
Justification (Instance vs. Static): This method reads the state (currentGPA) of a
specific object to perform its check. Since the result depends entirely on the unique
GPA value of that one student instance, it must be an instance method.
Task C: Constructors Role
Specific Purpose: A constructor is a special type of method whose sole purpose is to
initialize a newly created objects instance variables (attributes) immediately after
memory is allocated for it. It ensures the object is created in a valid, usable state. It
always shares the same name as the class and has no return type.
Contrast:
Default Constructor: This is automatically generated by the compiler if the
programmer defines no other constructors. It takes no arguments (zero
parameters) and performs basic, default initialization (0 for numbers, null for
references).
Parameterized Constructor: This is explicitly defined by the programmer and
accepts one or more parameters. These parameters are used to set the initial values
of the objects attributes, allowing the programmer to enforce a specific, required
initial state.
Best Practice Justification:
It is best practice to use a parameterized constructor to set initial attributes because
it guarantees that the object is instantiated in a valid and complete state in a single
step.
Immutability: For attributes like studentID that should never change, setting them
in a constructor is often the only time they are set, ensuring they are effectively
read-only afterward.
Safety: It prevents the possibility of a partial object existing in the system (e.g., an
object with a null ID) between the time it is created and the time the user
remembers to call the necessary setter methods. It enforces the rule: if you create an
object, you must provide its essential data.
Solution 3: Encapsulation and Data Hiding
Task A: The Need for Getters and Setters
If an instance variable is declared private, it means it can only be accessed or
modified within the class itself. From an external class (like the main method),
attempting to access myObject.privateAttribute results in a compilation error.
Need for Getters/Setters:
We provide public getter and setter methods to create a controlled gateway for
external access.
Getters (Accessors): public type getAttributeName(): Allows external classes to read
the attributes value.
Setters (Mutators): public void setAttributeName(type value): Allows external
classes to change the attributes value, but only through the control of the methods
logic.
Validation Scenario in a Setter:
If we have a private double gradePoint; attribute, the setter method can validate the
input:
public void setGradePoint(double newGrade) {
// Input Validation Logicif (newGrade >= 0.0 && newGrade <= 4.0)
{ this.gradePoint = newGrade;} else
{ System.out.println("Error: Grade must be between 0.0 and
4.0. Value rejected.");}
}
This is the essence of encapsulation: the public method enforces business rules,
protecting the integrity of the private data attribute.
Task B: The this Keyword
The this keyword is a reference to the current object (the object whose method or
constructor is being executed).
Primary Use 1: Differentiating Instance Variables
this is used to distinguish between a local variable (often a method parameter) and
an instance variable when they share the same name.
Code Snippet (Parameterized Constructor):
public class Textbook {
private String title;// Parameter 'title' hides the instance
variable 'title'public Textbook(String title) { // Use
'this.title' to refer to the instance attribute this.title =
title; }
}
Primary Use 2: Calling another Constructor (Constructor Chaining)
this() is used inside one constructor to call another constructor in the same class
(often used to avoid code duplication).
Code Snippet (Constructor Chaining):
public Textbook() {
// Calls the 3-parameter constructor with default
valuesthis("Unknown Title", "Unknown Author", 0);
}
public Textbook(String title, String author, int pages) {
this.title = title;// ...
}
Task C: Analyzing Code Structure (Debugging)
Flawed Class Snippet:
public class LibraryBook {
public String title;private int dueDate;public void
setTitle(String newTitle) { title = newTitle;}private int
getDueDate() { return dueDate;}
}
OOP Principle Violation: The title attribute is declared as public. This directly
violates the principle of Encapsulation/Data Hiding. It allows any external class to
directly modify the title attribute without passing through any validation or control
logic defined within the LibraryBook class.
Syntactical Flaw: The getter method getDueDate() is declared as private. Since the
attribute dueDate is also private, making the getter private means that the dueDate
is completely inaccessible (unreadable) from outside the LibraryBook class,
defeating the purpose of providing an accessor method. Accessor methods must
almost always be public.
Correction (Getter/Setter):
public class LibraryBook {
private String title; // CORRECTED: Should be privateprivate int
dueDate;// Corrected Setter (Mutator for title)public void
setTitle(String newTitle) { this.title = newTitle;}//
Corrected Getter (Accessor for dueDate)public int getDueDate()
{ // CORRECTED: Access modifier changed to public return
dueDate;}
}
Solution 4: Designing a Vehicle Class
Task A & B: Class Structure, Constructor, Getters, Setter with Logic, and drive
Method
public class Vehicle {
// 1. Attributes (Private Instance Variables)private String
make;private String model;private double fuelLevel; // 0.0 to
1.0// 2. Parameterized Constructorpublic Vehicle(String make,
String model, double fuelLevel) { // Use 'this' to resolve
ambiguity this.make = make; this.model = model; // Call
the setter for validation upon construction
setFuelLevel(fuelLevel); }// 3. Accessor (Getter) Methodspublic
String getMake() { return this.make;}public String getModel()
{ return this.model;}public double getFuelLevel() { return
this.fuelLevel;}// 4. Mutator (Setter) Method with
Validationpublic void setFuelLevel(double level) { if (level
>= 0.0 && level <= 1.0) { this.fuelLevel =
level; // System.out.println(this.make + " fuel set to: "
+ (level * 100) + "%"); } else
{ System.out.println("Error: Fuel level must be between
0.0 (empty) and 1.0 (full). Level rejected."); }}// Task B:
Behavior Implementation (Drive Method)public double drive(int
miles) { final double FUEL_CONSUMPTION_PER_MILE = 0.01;
// Calculate the maximum distance that can be traveled double
maxDistance = this.fuelLevel / FUEL_CONSUMPTION_PER_MILE; if
(miles > maxDistance) { // Vehicle runs out of fuel
double actualMilesDriven = maxDistance; this.fuelLevel =
0.0; System.out.println(this.make + " drove " +
actualMilesDriven + " miles and ran out of gas."); return
actualMilesDriven; } else { // Successful trip
double fuelConsumed = miles * FUEL_CONSUMPTION_PER_MILE;
this.fuelLevel -= fuelConsumed;
System.out.println(this.make + " drove " + miles + " miles.
Remaining fuel: " + (this.fuelLevel * 100) + "%"); return
miles; }}
}
Solution 5: Object Interaction and Method Chaining
Task A: Instantiation and Initial State
// Assume Vehicle class from Exercise 4 is accessible
Vehicle car1 = new Vehicle("Toyota", "Prius", 0.85); // Fuel = 0.85
Vehicle car2 = new Vehicle("Ford", "F150", 0.50); // Fuel = 0.50
// Initial States:
// car1.fuelLevel: 0.85
// car2.fuelLevel: 0.50
Task B: Method Chaining and State Change
car1 drives 50 miles.
Fuel consumed:
50 ×0.01=0.50
Operation: car1.drive(50);
New fuelLevel:
0.85 −0.50=0.35
Output: "Toyota drove 50 miles. Remaining fuel: 35.0%"
Attempt to set car2s fuel level to 1.5.
Operation: car2.setFuelLevel(1.5);
Printed Output: "Error: Fuel level must be between 0.0 (empty) and 1.0 (full). Level
rejected." (The validation logic in the setter rejected the input.)
Resulting fuelLevel:
0.50
(Unchanged)
car2 attempts to drive 60 miles.
Max distance available: car2.fuelLevel /
0.01=0.50/0.01=50
miles.
Since
60>50
, the car runs out of fuel.
Operation: double actualDistance = car2.drive(60);
Actual distance driven:
50.0
miles.
Final fuelLevel:
0.0
Output: "Ford drove 50.0 miles and ran out of gas."
Task C: Design for Inter-Object Behavior
If implementing transferFuel(Vehicle recipient, double amount), the recipient object
must be passed as a parameter because the method needs a reference to the second
object involved in the transaction.
The method needs to access the recipient objects setter method
(recipient.setFuelLevel()) to increase its fuel.
The method itself is called on the source object (sourceCar.transferFuel(targetCar,
0.1)), and the sourceCar can access its own internal fuelLevel directly using this. It
has no innate access to other objects unless they are explicitly provided.
Method Signature:
public void transferFuel(Vehicle recipient, double amount)
Solution 6: Static vs. Instance Members
Task A: Designing the University Class
Member
Nature (Static/Instance)
Access (Private/Public)
Justification
1. Campus Name
Static
Private
The name is the same for all instances of the University class (e.g., if you create two
University objects, they represent the same institution). Static ensures only one
copy exists for the class. Private protects it from arbitrary modification.
2. Current Enrollment
Static
Private
Enrollment is a collective property of the campus, not an individual object instance.
All objects must share and modify the single, true count. Private ensures the count
can only be changed via the controlled increaseEnrollment method.
3. increaseEnrollment()
Static
Public
Since this method modifies a static attribute (Current Enrollment), it must also be
static. It can be called without needing a specific University object instance. Public
allows external classes to use this official method.
4. getCampusName()
Static
Public
Since the attribute it reads (Campus Name) is static, the method should also be
static. This allows users to read the constant campus name without having to
instantiate a University object.
Task B: Static Initialization
A private static final attribute is a constant value that belongs to the class and can
never be changed after initialization.
Initialization:
public class University {
// Defined and initialized at the same timeprivate static final
int MAX_STUDENT_CAPACITY = 40000; // ... other members
}
Reason for Immediate Definition and Immutability:
static: It exists and is initialized when the class is loaded by the JVM (before any
object is created).
final: This keyword means the value can only be assigned once.
Since the value is initialized upon class loading, it cannot be changed later by an
instance method because instance methods only execute after an object has been
created. Allowing an instance method to change a final value would violate the
fundamental principle of finality.
Task C: The Static Utility Case
A common example is the Math class in Java:
Class: java.lang.Math
Example Method: Math.sqrt(double a) (calculates the square root)
Why it is Structured as Static:
The Math class provides mathematical functions that are universal and do not
depend on the state of any specific object.
To calculate the square root of 9, you dont need a "Math object" with specific
attributes. The operation is purely functional.
By making the methods static, the programmer saves the overhead and memory
required to create a Math object (e.g., Math m = new Math();) every time they need
to perform a simple calculation. You can simply call the method directly on the class
name: Math.sqrt(x).
Solution 7: References and the Heap
Task A: Heap vs. Stack
Memory Region
What is Stored
Example: Vehicle myCar = new Vehicle(...);
Stack
Stores primitive local variables (e.g., int x, boolean isReady) and Reference
Variables. The Stack manages method calls and the flow of execution.
Stores the reference variable myCar. This variable holds the memory address (the
pointer) of the actual object.
Heap
Stores the actual Objects (instances) and their instance variables (attributes). The
Heap is used for dynamic memory allocation, and its content persists until the object
is no longer referenced and is cleaned up by the GC.
Stores the actual Vehicle object (with its make, model, and fuelLevel attributes).
Task B: Multiple References and Aliasing
How many Vehicle objects exist in memory?
Two objects exist.
Object 1 is created by v1 = new Vehicle(...)
Object 2 is created by v2 = new Vehicle(...)
v3 = v1 does not create a third object; it only creates a third reference variable (v3)
that points to Object 1.
What is the value of v3.getFuelLevel()?
The value is 0.95.
Since v3 and v1 point to the same object (Object 1), calling v1.setFuelLevel(0.95)
changes the state of Object 1. When v3 reads the state of Object 1, it sees the new,
updated value.
If v2 = v1; and then v2.setFuelLevel(0.1); was executed, what would be
v3.getFuelLevel()?
The value of v3.getFuelLevel() would be 0.1.
Aliasing: The line v2 = v1; causes v2 to stop pointing to Object 2 and start pointing
to Object 1 (the same object that v1 and v3 point to). The variable v2 is now an alias
for Object 1.
The original Object 2 is now unreachable and becomes eligible for Garbage
Collection.
Calling v2.setFuelLevel(0.1) modifies the shared Object 1. Since v3 still points to
Object 1, it reflects the change.
Solution 8: Passing Objects to Methods (Call by Value)
Task A: Method Parameter Scope (Creating a New Object)
If the method signature is public void modifyVehicle(Vehicle car) and the line car =
new Vehicle("New Make", "New Model", 0.0); is executed inside, the original object
will NOT be changed.
Reasoning (Pass by Value):
When you call modifyVehicle(myCar), a copy of the reference stored in myCar is
passed into the modifyVehicle method and stored in the local parameter variable
car.
The line car = new Vehicle(...) changes where the local parameter variable car points
(it points to a brand new object).
The original reference variable myCar (in the calling method/scope) still points to
the original object in the Heap. The local change to the parameter variable car has
no effect outside the methods scope.
Task B: Modifying Attributes via Reference
If you execute car.setFuelLevel(0.0); inside the modifyVehicle method, the original
object passed into the method WILL be changed.
Reasoning (Accessing the Shared Object):
The parameter variable car still holds a copy of the reference to the original object.
Executing car.setFuelLevel(...) uses the reference to navigate to the original object in
the Heap and execute one of its instance methods.
Since the objects state (its fuelLevel attribute) is modified, this change is permanent
and visible to the original reference variable (myCar) when the method returns.
Differentiation:
Task A changes which object the local reference points to (changes the reference
itself). The original object is unaffected.
Task B changes the internal state of the object the local reference points to (changes
the objects attributes). The original object is affected.
Solution 9: Garbage Collection and Object Lifecycle
Task A: Object Lifetime and Garbage Collection (GC) Eligibility
An object becomes eligible for Garbage Collection (GC) when no active reference
variable in the program can reach or access that object. In simpler terms, the object
is "unreachable" or "orphaned."
GC Mechanism Timing:
The GC runs automatically in the background, managed by the JVM. It is generally
non-deterministic, meaning the programmer cannot guarantee when it will run.
However, the JVM often triggers the GC when:
The available memory (Heap) drops below a certain threshold (when the program
needs more space).
The application has entered a period of low activity.
Task B: Object Destruction (Conceptual)
The conceptual flow of an objects life cycle is:
Declaration: The reference variable is declared on the Stack (e.g., Vehicle car;).
Instantiation and Allocation: The new keyword allocates memory in the Heap, and
the constructor initializes the objects attributes. The reference variable is assigned
the memory address (car = new Vehicle(...)).
Use: The object is used by the program (methods are called, state is read/modified).
Reference Loss: All active references pointing to the object are either explicitly set to
null (e.g., car = null;) or go out of scope (e.g., the method/block they were defined in
finishes execution). The object is now unreachable.
GC Eligibility: The unreachable object is marked as eligible for Garbage Collection.
Deallocation (Collection): At some non-deterministic point, the GC runs, identifies
the unreachable object, and reclaims its memory space in the Heap, making it
available for new object allocations.
Task C: Scope and Reference Loss
public static void main(String[] args) {
{ // Start of Inner Scope Vehicle truck = new Vehicle("GMC",
"Sierra", 0.75); // ... some operations on truck} // End of
Inner Scope// Can truck be accessed here?
}
At "End of Inner Scope" line: The variable truck is a local variable whose scope is
defined by the inner curly braces {}. When the execution exits this block, the truck
reference variable is destroyed (removed from the Stack).
Object Eligibility: Since the only reference to the Vehicle object (the reference stored
in truck) is destroyed, the object itself becomes unreachable and is immediately
eligible for garbage collection.
Access: The variable truck cannot be accessed outside the inner scope because it no
longer exists on the Stack. Any attempt to use it will result in a compilation error
("cannot find symbol").