Implementing Complex Data Types with Java Classes
Classes and Objects
Classes
- A class is a blueprint for creating objects. It defines the data members (attributes) and methods (functions) that the objects created from the class will have.
- In Java, classes are defined using the
classkeyword. The general syntax is:
class ClassName {
// Data members (attributes)
// Methods (functions)
}
Objects
- An object is an instance of a class. It contains state (data) and behavior (methods).
- The process of creating an object is called instantiation.
- Objects are created using the
newkeyword, which allocates memory for the object. For example:
Rectangle r1 = new Rectangle(); // Creates an object of Rectangle class
Example Program: Classes and Objects
Here’s a breakdown of the example provided in the text:
package classesandobjectsproject;
import java.util.*;
class Rectangle {
private int len, brd; // Data members (attributes)
// Method to get data from the user
public void getData() {
Scanner scn = new Scanner(System.in);
System.out.println("Enter length and breadth:");
len = scn.nextInt();
brd = scn.nextInt();
}
// Method to set data directly
public void setData(int l, int b) {
len = l;
brd = b;
}
// Method to display data
public void displayData() {
System.out.println("Length = " + len);
System.out.println("Breadth = " + brd);
}
// Method to calculate area and perimeter
public void areaPeri() {
int area = len * brd;
int perimeter = 2 * (len + brd);
System.out.println("Area = " + area);
System.out.println("Perimeter = " + perimeter);
}
}
public class ClassesAndObjectsProject {
public static void main(String[] args) {
Rectangle r1, r2, r3; // Define three reference variables
r1 = new Rectangle(); // Create first object
r2 = new Rectangle(); // Create second object
r3 = new Rectangle(); // Create third object
r1.setData(10, 20); // Set data for r1
r1.displayData(); // Display r1's data
r1.areaPeri(); // Calculate and print area and perimeter for r1
r2.setData(5, 8); // Set data for r2
r2.displayData(); // Display r2's data
r2.areaPeri(); // Calculate and print area and perimeter for r2
r3.getData(); // Receive data from keyboard for r3
r3.displayData(); // Display r3's data
r3.areaPeri(); // Calculate and print area and perimeter for r3
}
}
Program Explanation
- Data Members: The class
Rectanglehas two private data members,len(length) andbrd(breadth). Making them private restricts direct access from outside the class, protecting the integrity of the data. - Methods:
getData(): A method that prompts the user to enter the length and breadth.setData(int l, int b): A method to set the length and breadth directly using parameters.displayData(): Displays the current values of length and breadth.areaPeri(): Calculates and displays the area and perimeter based on the current values of length and breadth.
- Main Class: The
ClassesAndObjectsProjectclass contains themain()method, which is the entry point of the program.- Three
Rectangleobjects (r1,r2,r3) are created. - Data is set for
r1andr2usingsetData(), and results are displayed. - For
r3, data is obtained from user input through thegetData()method.
- Three
Access Modifiers
- Private: Data members (
lenandbrd) are declared private, which means they cannot be accessed directly outside the class. - Public: The methods (
getData(),setData(),displayData(),areaPeri()) are public, allowing other classes to access them. This provides controlled access to the private data members.
Constructors
What is a Constructor?
- A constructor is a special method that is called when an object is instantiated. It has the same name as the class and does not have a return type.
- Constructors are used to initialize objects, often setting initial values for the data members.
Types of Constructors
- Zero-Argument Constructor: A constructor that does not take any parameters. It initializes data members to default values (e.g., 0, null).
- Parameterized Constructor: A constructor that takes parameters to initialize data members with specific values at the time of object creation.
Example Program: Constructors
Here’s another example demonstrating constructors:
package constructorsproject;
import java.util.*;
class Number {
private int i;
// Zero-argument constructor
public Number() {
}
// One-argument constructor
public Number(int j) {
i = j;
}
public void setData(int j) {
i = j;
}
public void getData() {
Scanner scn = new Scanner(System.in);
System.out.println("Enter any integer:");
i = scn.nextInt();
}
public void displayData() {
System.out.println("Value of i = " + i);
}
}
public class ConstructorsProject {
public static void main(String[] args) {
Number n1, n2, n3;
n1 = new Number(); // Calls zero-argument constructor
n1.displayData(); // Displays default value (0)
n1.setData(200); // Sets value using setData()
n1.displayData(); // Displays updated value
n2 = new Number(); // Calls zero-argument constructor
n2.displayData(); // Displays default value (0)
n2.getData(); // Gets input from the user
n2.displayData(); // Displays user-input value
n3 = new Number(100); // Calls one-argument constructor
n3.displayData(); // Displays value (100)
}
}
Constructor Explanation
- In this example, the
Numberclass has both a zero-argument constructor and a one-argument constructor. - When
n1andn2are created using the zero-argument constructor, the default value ofiis0. - The value of
ican later be set using thesetData()method or obtained through user input viagetData(). n3is instantiated with the one-argument constructor, which initializesidirectly to100.
Object Lifecycle and Memory Management
Memory Allocation
- When an object is created using the
newoperator, memory is allocated for that object on the heap. - The reference variable (like
r1,n1, etc.) is stored on the stack, holding the memory address of the object.
Garbage Collection
- Java has an automatic Garbage Collector that manages memory. It periodically checks for objects that are no longer referenced and reclaims memory, preventing memory leaks.
- This is different from languages like C++, where the programmer must manually manage memory (allocating and freeing it).
Finalize Method
- The
finalize()method is defined in theObjectclass and can be overridden to perform cleanup operations (like closing files or releasing resources) before an object is destroyed by the garbage collector. - It is called by the garbage collector, but there’s no guarantee when it will be called.
Example Program: Finalize Method
Here’s an example of how the finalize() method works:
package objectdestructionproject;
class Example {
private int data;
public Example() { // Constructor
System.out.println("Inside the constructor");
}
protected void finalize() throws Throwable {
System.out.println("Inside finalize method");
super.finalize(); // Call to superclass finalize
}
}
public class ObjectDestructionProject {
public static void main(String[] args) {
Example e = new Example(); // Object creation
e = null; // Nullifying reference
System.gc(); // Suggest garbage collection
}
}
Finalization Explanation
- In this example, when the
Exampleobject is no longer referenced (by settingetonull), the garbage collector is suggested to run usingSystem.gc(). - Before the object’s memory is reclaimed, the
finalize()method is called, allowing for any necessary cleanup.
Complex Class Implementation
Class Definition: The Complex class is designed to represent complex numbers with a real and imaginary part.
class Complex {
private float real, imag;
...
}
Constructors:
- A default constructor initializes a
Complexobject without setting its values.An overloaded constructor initializes aComplexobject with specified real and imaginary parts.
public Complex() {
}
public Complex(float r, float i) {
real = r;
imag = i;
}
Data Input Methods:
getData()method prompts the user to enter the real and imaginary parts of the complex number.setData(float r, float i)allows setting values for the complex number.
public void getData() {
...
}
public void setData(float r, float i) {
real = r;
imag = i;
}
Display Method: displayData() prints the real and imaginary parts of the complex number.
public void displayData() {
System.out.println("real = " + real);
System.out.println("imaginary = " + imag);
}
Arithmetic Operations:
addComplex(Complex y)adds two complex numbers and returns the result as a newComplexobject.mulComplex(Complex y)multiplies two complex numbers and returns the result.
public Complex addComplex(Complex y) {
Complex t = new Complex();
t.real = real + y.real;
t.imag = imag + y.imag;
return t;
}
public Complex mulComplex(Complex y) {
Complex t = new Complex();
t.real = real * y.real - imag * y.imag;
t.imag = real * y.imag + y.real * imag;
return t;
}
Main Class for Testing
Creating Complex Numbers: The main method creates instances of Complex and performs addition and multiplication on them.
public class ComplexNumbersProject {
public static void main(String[] args) {
Complex c1 = new Complex();
c1.setData(2.0f, 2.0f);
Complex c2 = new Complex();
Complex c3 = c1.addComplex(c2);
...
}
}
Chaining Method Calls: The program demonstrates the ability to chain method calls, such as adding the result of a multiplication directly to another complex number.
c7 = c1.addComplex(c2.mulComplex(c3));
The this Reference
- The
thiskeyword is used to refer to the current object instance. It helps distinguish between instance variables and parameters with the same name, particularly when they are set within methods.
public void setData(int i) {
this.i = i; // Uses 'this' to refer to the instance variable
}
Static Members
- Static members (both variables and methods) belong to the class rather than instances. They are shared among all instances of the class, which is useful for maintaining shared data, like a count of how many objects have been created
class Ex {
private static int count = 0;
...
public static void showCount() {
System.out.println(count);
}
}
Passing Objects to Functions
- Objects are passed by reference, meaning if you modify an object’s data within a method, the changes will reflect outside the method as well.
static void fun(Ex p) {
p.setData(3, 8.5f);
}