Types of Classes in Java
Java is a widely-used programming language that is popular among developers due to its versatility and ease of use. It is an Object-oriented programming language that is widely used to build various applications. One of the key features of Java is its support for classes, which are templates for creating objects. Classes are a fundamental component of Java that allow developers to define objects and their characteristics.
There are seven types of classes in Java that have different properties and purposes.
- Static Class
- Final Class
- Abstract Class
- Concrete Class
- Singleton Class
- POJO Class (Plain Old Java Object)
- Inner Class (Non-static Nested Class)
1.Static Class:
In Java, a static class is a nested class that has the "static" keyword in its definition. Unlike non-static nested classes, static classes can be accessed without creating an instance of the enclosing class. It is because a static class is not associated with any instance of the enclosing class.
Syntax:
public static class MyStaticClass {
// static methods and fields go here
}
Purpose:
- Static classes are commonly used to group related functionality together. By defining related methods and fields in a single static class, code organization can be improved.
- Since a static class does not require instantiation, it can help improve performance by reducing the number of objects created.
- Similar to the previous point, the lack of instantiation required for static classes also helps reduce memory usage.
- Static classes can be used to create helper classes that provide a set of related methods. These helper classes can be used in conjunction with the main class to provide additional functionality.
- Java's utility classes often consist of static classes. These utility classes provide a set of commonly used functions for developers to use without needing to implement them from scratch.
Properties:
- A static class is a nested class that has the "static" keyword in its definition.
- Static classes can be accessed without creating an instance of the enclosing class.
- Static classes cannot access non-static members of the enclosing class.
- Static classes can have static fields, methods, and nested classes.
ALGORITHM:
Step 1: Define a public class called "StaticClassExample".
Step 2: Define the main method within the "StaticClassExample" class.
Step 3: Call the static "add" method of the "StaticMath" class with the arguments 2 and 3 and assign the result to a variable called "result".
Step 4: Print out the value of the "result" variable.
Step 5: Attempt to create an instance of the "StaticMath" class (which is not allowed because the class is static), and comment out this line of code to prevent a compilation error.
Step 6: Define a static class called "StaticMath" within the "StaticClassExample" class.
Step 7: Define a static method called "add" within the "StaticMath" class that takes two integer arguments and returns their sum.
End the program.
Implementation:
FileName: StaticClassExample.java
import java.util.*;
public class StaticClassExample {
public static void main(String[] args) {
// Call the static method of the static class without creating an instance
int result = StaticMath.add(2, 3);
System.out.println("Result: " + result);
// Attempt to create an instance of the static class (which is not allowed)
// This line of code will result in a compilation error
// StaticMath math = new StaticMath();
}
// A static class with a static method
static class StaticMath {
// A static method that adds two integers and returns the result
public static int add(int a, int b) {
return a + b;
}
}
}
Output:
Result: 5
2.Final Class:
In Java, a final class is a class that cannot be extended or subclassed. It means that once a final class is defined, it cannot be further modified or extended by any other class. Final classes are often used in Java to ensure that a class cannot be modified, ensuring its stability and consistency. To define a final class in Java, the "final" keyword is used in the class definition.
Syntax:
final class MyFinalClass {
// code goes here
}
Purpose:
- Final classes are often used to ensure the stability and consistency of a class. By preventing subclasses from modifying or extending a class, a final class can ensure that its behavior and implementation remain consistent over time.
- Final classes can help to improve performance by allowing the JVM to optimize the class's methods and fields for better performance.
- Final classes are often used to create immutable classes. Immutable classes are classes whose instances cannot be modified once they are created. By defining a final class with final fields, an immutable class can be created that is thread-safe and guarantees that its instances remain consistent over time.
- Final classes can be used to prevent subclassing and ensure that the class's functionality remains unchanged. It is useful in situations where the class is intended to be used as is and should not be modified or extended.
- Final classes can be used to ensure security by preventing subclasses from modifying or extending a class in ways that could compromise security.
Properties:
- A final class is a class that cannot be extended or subclassed.
- All the methods and fields of a final class are implicitly final.
- Final classes cannot be modified or extended by any other class.
- Final classes are often used to create immutable classes.
ALGORITHM:
Step 1: Define a final class ImmutablePerson with three private final instance variables firstName, lastName, and age.
Step 2: Define a constructor that sets the values of these instance variables.
Step 3: Define getter methods for each instance variable.
Step 4: Create a public class FinalClassExample to test the ImmutablePerson class.
Step 5: Create an instance of the ImmutablePerson class and initialize it with values for firstName, lastName, and age.
Step 6: Attempt to modify the instance variables (which is not allowed).
Step 7: Print out the values of the instance variables using the getter methods.
FileName: FinalClassExample.java
import java.util.*;
// Define a final class that cannot be subclassed
final class ImmutablePerson {
// Declare private final instance variables to ensure immutability
private final String firstName;
private final String lastName;
private final int age;
// Define a constructor to set the values of the instance variables
public ImmutablePerson(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// Define getter methods for the instance variables
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
}
// Create a public class to test the final class
class FinalClassExample {
public static void main(String[] args) {
// Create a new instance of the immutable person class
ImmutablePerson person = new ImmutablePerson("John", "Doe", 30);
// Attempt to modify the instance variables (which is not allowed)
// This line of code will result in a compilation error
// person.firstName = "Jane";
// Print out the values of the instance variables
System.out.println("First Name: " + person.getFirstName());
System.out.println("Last Name: " + person.getLastName());
System.out.println("Age: " + person.getAge());
}
}
Output:
First Name: John
Last Name: Doe
Age: 30
3.Abstract Class:
In Java, an abstract class is a class that is declared with the "abstract" keyword in its definition. An abstract class is not intended to be instantiated on its own, but rather serves as a base class for its subclasses to inherit from. Abstract classes can define method signatures without providing the method implementation, which is then implemented by the subclass.
Purpose:
- To define a common interface or behavior that can be shared by a group of related classes.
- To provide a template or blueprint for creating concrete classes that inherit from it.
- To enforce a contract or set of rules that any subclass must adhere to by defining a set of abstract methods that the subclass must implement.
- To allow for the extension of functionality in a program without modifying existing code, by adding new concrete subclasses that inherit from the abstract class.
- To facilitate polymorphism in a program, where objects of different concrete classes can be treated as instances of the same abstract class.
- To abstract away implementation details and provide a higher-level view of a class hierarchy, making the code more maintainable and easier to understand.
- To separate the interface from the implementation of a class, allowing for more flexibility in changing the implementation without affecting the interface.
Properties:
- An abstract class cannot be instantiated directly. It can only be used as a superclass for other concrete or abstract classes.
- An abstract class may or may not contain abstract methods.
- An abstract class can have constructors and instance variables.
- An abstract class can have both abstract and non-abstract methods.
- An abstract class can be used as a type for references and variables.
ALGORITHM:
Step 1: Define an abstract class Shape with protected instance variables color and filled, a constructor to set these values, abstract methods to get area and perimeter, and getter and setter methods for the instance variables.
Step 2: Define a subclass of Shape called Circle with a private instance variable radius, a constructor to set the values of the instance variables, implementations of the abstract methods to calculate area and perimeter, and a toString() method to display information about the circle.
Step 3: Define a subclass of Shape called Rectangle with private instance variables length and width, a constructor to set the values of the instance variables, implementations of the abstract methods to calculate area and perimeter, and a toString() method to display information about the rectangle.
Step 4: Create a public class called AbstractClassExample to test the Shape, Circle, and Rectangle classes.
Step 5: In the main method of AbstractClassExample, create a new instance of the Circle class and display information about the circle.
Step 6: Create a new instance of the Rectangle class and display information about the rectangle.
Step 7: Change the color and filled status of the rectangle using setter methods.
Step 8: Display updated information about the rectangle.
FileName: AbstractClassExample.java
import java.util.*;
// Define an abstract class to represent a shape
abstract class Shape {
// Declare protected instance variables to be used by subclasses
protected String color;
protected boolean filled;
// Define a constructor to set the values of the instance variables
public Shape(String color, boolean filled) {
this.color = color;
this.filled = filled;
}
// Define abstract methods that must be implemented by subclasses
public abstract double getArea();
public abstract double getPerimeter();
// Define getter and setter methods for the instance variables
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public boolean isFilled() {
return filled;
}
public void setFilled(boolean filled) {
this.filled = filled;
}
// Define a toString() method to display information about the shape
public String toString() {
return "Shape[color=" + color + ",filled=" + filled + "]";
}
}
// Define a subclass of Shape to represent a Circle
class Circle extends Shape {
// Declare private instance variable to represent the radius of the circle
private double radius;
// Define a constructor to set the values of the instance variables
public Circle(String color, boolean filled, double radius) {
super(color, filled);
this.radius = radius;
}
// Implement the abstract methods of the Shape class to calculate the area and perimeter of the circle
public double getArea() {
return Math.PI * radius * radius;
}
public double getPerimeter() {
return 2 * Math.PI * radius;
}
// Define a toString() method to display information about the circle
public String toString() {
return "Circle[" + super.toString() + ",radius=" + radius + "]";
}
}
// Define a subclass of Shape to represent a Rectangle
class Rectangle extends Shape {
// Declare private instance variables to represent the length and width of the rectangle
private double length;
private double width;
// Define a constructor to set the values of the instance variables
public Rectangle(String color, boolean filled, double length, double width) {
super(color, filled);
this.length = length;
this.width = width;
}
// Implement the abstract methods of the Shape class to calculate the area and perimeter of the rectangle
public double getArea() {
return length * width;
}
public double getPerimeter() {
return 2 * (length + width);
}
// Define a toString() method to display information about the rectangle
public String toString() {
return "Rectangle[" + super.toString() + ",length=" + length + ",width=" + width + "]";
}
}
// Create a public class to test the Shape, Circle, and Rectangle classes
class AbstractClassExample {
public static void main(String[] args) {
// Create a new instance of the Circle class
Circle circle = new Circle("Red", true, 5.0);
// Display information about the circle
System.out.println(circle);
System.out.println("Area: " + circle.getArea());
System.out.println("Perimeter: " + circle.getPerimeter());
// Create a new instance of the Rectangle class
Rectangle rectangle = new Rectangle("Blue", false, 4.0, 6.0);
// Display information about the rectangle
System.out.println("Rectangle");
System.out.println("Area: " + rectangle.getArea());
System.out.println("Perimeter: " + rectangle.getPerimeter());
// Change the color and filled status of the rectangle
rectangle.setColor("Green");
rectangle.setFilled(true);
// Display updated information about the rectangle
System.out.println("Updated Rectangle");
System.out.println(rectangle);
System.out.println("Area: " + rectangle.getArea());
System.out.println("Perimeter: " + rectangle.getPerimeter());
}
}
Output:
Circle[Shape[color=Red,filled=true],radius=5.0]
Area: 78.53981633974483
Perimeter: 31.41592653589793
Rectangle[Shape[color=Blue,filled=false],length=4.0,width=6.0]
Area: 24.0
Perimeter: 20.0
Updated Rectangle
Rectangle[Shape[color=Green,filled=true],length=4.0,width=6.0]
Area: 24.0
Perimeter: 20.0
4.Concrete Class:
In Java, a concrete class is a class that has a complete implementation and can be instantiated to create objects. Unlike an abstract class, a concrete class can be instantiated directly and can be used to create objects. It provides a full implementation of all its methods and can be used to define objects that can interact with other objects in a Java program.
Purpose:
- Provides a specific implementation for an abstract or generic concept defined by an interface or abstract class.
- Allows for code reuse by defining common functionality in a superclass or interface and implementing it in multiple subclasses.
- Provides a way to encapsulate data and behavior within a single entity, improving modularity and organization in code.
Properties:
- Can be instantiated to create objects.
- Implements all the methods declared in its interface or superclass.
- May define additional methods and variables specific to its functionality.
ALGORITHM:
Step 1: Create a new Java class called "Car"
Step 2: Declare the private instance variables "make", "model", and "year" as String and int respectively
Step 3: Define a constructor with parameters "make", "model", and "year" to initialize the instance variables
Step 4: Define getter and setter methods for each of the instance variables
Step 5: Define a method called "displayCarInfo" to display the make, model, and year of the car
Step 6: Define a main function to test the Car class
Step 7: Create a new Car object with the make "Toyota", model "Camry", and year 2020
Step 8: Call the "displayCarInfo" method on the Car object to display its information
Step 9: Use the "setMake" method to change the make of the car to "Honda"
Step 10: Call the "displayCarInfo" method again to display the updated information about the car
FileName: Car.java
import java.util.*;
// Define a Concrete class to represent a Car
public class Car {
// Declare private instance variables to represent the make, model, and year of the car
private String make;
private String model;
private int year;
// Define a constructor to set the values of the instance variables
public Car(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
// Define getter and setter methods for the instance variables
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
// Define a method to display information about the car
public void displayCarInfo() {
System.out.println("Make: " + make);
System.out.println("Model: " + model);
System.out.println("Year: " + year);
}
// Main function to test the Car class
public static void main(String[] args) {
// Create a Car object and set its make, model, and year
Car myCar = new Car("Toyota", "Camry", 2020);
// Display information about the car
myCar.displayCarInfo();
// Change the make of the car using the setMake() method
myCar.setMake("Honda");
// Display the updated information about the car
myCar.displayCarInfo();
}
}
Output:
Make: Toyota
Model: Camry
Year: 2020
Make: Honda
Model: Camry
Year: 2020
5.Singleton Class:
In Java, a Singleton class is a class that can have only one object (an instance of the class) at a time. The class provides a global point of access to that instance, which can be accessed from anywhere within the application.
Purpose:
- To ensure that only one instance of the class exists in the JVM.
- To provide a global point of access to the object.
- To control the creation and initialization of the object.
- To restrict the number of instances that can be created.
- To provide a way to access the instance of the class without creating a new object every time.
Properties:
- Private Constructor: A singleton class must have a private constructor to restrict the creation of objects from outside of the class.
- Private static instance variable: A singleton class must have a private static instance variable which holds the only instance of the class.
- Public static method: A singleton class must have a public static method to access the instance of the class. The method is used to return the instance of the class.
ALGORITHM:
Step 1: Declare a private static instance variable of the Singleton class.
Step 2: Declare a private constructor to prevent the creation of multiple instances of the class.
Step 3: Define a public static method to create and return the Singleton instance.
Step 4: Check if the instance is null, and if it is, create a new Singleton instance.
Step 5: Return the Singleton instance.
Step 6: Define a public method to demonstrate the functionality of the Singleton instance.
Step 7: In the main function, create two instances of the Singleton class.
Step 8: Display the memory addresses of the two instances.
Step 9: Demonstrate that both instances refer to the same Singleton object.
Step 10: Call the showMessage() method using one of the Singleton instances.
FileName: Singleton.java
import java.util.*;
public class Singleton {
// Declare a private static instance variable of the Singleton class
private static Singleton instance;
// Declare a private constructor to prevent the creation of multiple instances of the class
private Singleton() {}
// Define a public static method to create and return the Singleton instance
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// Define a public method to demonstrate the functionality of the Singleton instance
public void showMessage() {
System.out.println("Hello World!");
}
// Main function to test the Singleton class
public static void main(String[] args) {
// Create two instances of the Singleton class
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
// Display the memory addresses of the two instances
System.out.println("Memory address of obj1: " + obj1);
System.out.println("Memory address of obj2: " + obj2);
// Demonstrate that both instances refer to the same Singleton object
if (obj1 == obj2) {
System.out.println("obj1 and obj2 refer to the same Singleton instance.");
} else {
System.out.println("obj1 and obj2 refer to different Singleton instances.");
}
// Call the showMessage() method using one of the Singleton instances
obj1.showMessage();
}
}
Output:
Memory address of obj1: Singleton@3af49f1c
Memory address of obj2: Singleton@3af49f1c
obj1 and obj2 refer to the same Singleton instance.
Hello World!
6. POJO Class (Plain Old Java Object):
A POJO (Plain Old Java Object) is a Java class that encapsulates only fields with getters and setters methods. The POJO class does not depend on any external framework, making it simple, easy to understand, and reusable.
Purpose:
- Standardized way to represent data objects
- Easily share data between different layers of an application
- Simple and reusable code
- Easily maintainable and testable code
- Essential component of object-oriented programming practices
- Ideal for use in modern software development, particularly in enterprise application development
- Enables the creation of applications that are easy to scale
Properties:
- Plain and simple Java class.
- Encapsulates data using getters and setters.
- No external framework dependencies
- Serializable
ALGORITHM:
Step 1: Create a Person class with name, age, and address as its properties.
Step 2: Define default and parameterized constructors for the class.
Step 3: Define getter and setter methods for the properties.
Step 4: In the main function:
Step 4.1: Create an instance of the Person class using the default constructor.
Step 4.2: Set the properties of the person object using the setter methods.
Step 4.3: Retrieve and display the properties of the person object using the getter methods.
Step 4.4: Create another instance of the Person class using the parameterized constructor.
Step 4.5: Retrieve and display the properties of the person object using the getter methods.
FileName: Person.java
import java.util.*;
public class Person {
// Properties of the class
private String name;
private int age;
private String address;
// Default constructor
public Person() {
// Empty constructor
}
// Parameterized constructor
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
// Getter and setter methods for the properties
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// Main function to demonstrate usage of POJO class
public static void main(String[] args) {
// Create an instance of the Person class using the default constructor
Person person1 = new Person();
// Set properties using setter methods
person1.setName("Chandu");
person1.setAge(20);
person1.setAddress("123 Hyderabad, Anytown India");
// Retrieve and display properties using getter methods
System.out.println("Name: " + person1.getName());
System.out.println("Age: " + person1.getAge());
System.out.println("Address: " + person1.getAddress());
// Create another instance of the Person class using the parameterized constructor
Person person2 = new Person("Rahul", 22, "456 Medak St, Anycity Telangana");
// Retrieve and display properties using getter methods
System.out.println("Name: " + person2.getName());
System.out.println("Age: " + person2.getAge());
System.out.println("Address: " + person2.getAddress());
}
}
Output:
Name: Chandu
Age: 20
Address: 123 Hyderabad, Anytown India
Name: Rahul
Age: 22
Address: 456 Medak St, Anycity Telangana
7.Inner Class (Non-static Nested Class):
In Java, an inner class is a class that is defined inside another class. It can be either static or non-static. A non-static inner class is also known as a nested class.
Purpose:
- Encapsulation of related functionality within a single class
- Improved code readability by grouping classes together
- Access to private members of outer class for implementing certain design patterns
- Event handling in Java GUIs
Properties:
- Scope: Inner classes have access to all members of outer class, including private members
- Instantiation: Inner class instances can only be created within an instance of the outer class
- Name: Inner class name is typically outer class name followed by dot and inner class name
- Modifiers: Inner classes can have the same modifiers as any other class, such as public, private, protected, and static
- Relationship to outer class: Non-static inner classes have an implicit reference to their outer class, which can be accessed using OuterClassName.this syntax.
ALGORITHM:
Step 1: Define the OuterClass with a private member variable x and a constructor to set its value.
Step 2: Define the non-static InnerClass inside OuterClass with a private member variable y and a constructor to set its value.
Step 3: Define a method sum() inside InnerClass that returns the sum of x and y.
Step 4: In the main method, create an instance of OuterClass and use it to create an instance of InnerClass.
Step 5: Call the sum() method of InnerClass to get the sum of x and y.
Step 6: Print the result.
FileName: OuterClass.java
import java.util.*;
public class OuterClass {
private int x; // private member variable of outer class
// constructor of outer class
public OuterClass(int x) {
this.x = x;
}
// non-static inner class definition
public class InnerClass {
private int y; // private member variable of inner class
// constructor of inner class
public InnerClass(int y) {
this.y = y;
}
// method of inner class that uses both inner and outer class members
public int sum() {
return x + y;
}
}
// main method to create instances of outer and inner classes
public static void main(String[] args) {
// create instance of outer class
OuterClass outer = new OuterClass(10);
// create instance of inner class using outer class instance
OuterClass.InnerClass inner = outer.new InnerClass(20);
// call sum method of inner class to use both outer and inner class members
int result = inner.sum();
// print result
System.out.println("Sum of x and y is: " + result);
}
}
Output:
Sum of x and y is: 30