Types Of Classes In Java: Abstract, Concrete, Final, Static

This tutorial will discuss various Types of Classes in Java like Abstract, Concrete, Final, Inner, POJO, Static & other special classes with examples:

In our previous tutorial, we discussed classes and objects in Java. A class in Java is a template or blueprint. It can also be defined as a collection of similar objects. We define objects of type class and then communicate via these objects.

Each object is an instance of a class that has a state and behavior.

=> Visit Here For The Exclusive Java Training Tutorial Series.

Types of classes in Java

Class Types In Java – Introduction

We all know that the class has the following components:

  • Modifiers: Specify access for the class.
  • ClassName: Name of the class.
  • KeyWords: Keywords suggesting if a class extends or implements class or interface.
  • The class Body enclosed in curly brackets {}

Depending on the different modifiers used, class body specified, and keywords used, we have various types of classes in Java.

  • Concrete class: A normal class that has the concrete implementation of methods.
  • POJO class: This is “Plain Old Java Object” containing only private member variables and getter setter methods to access these variables.
  • Abstract class: This class has one or more abstract methods.
  • Final class: A final class cannot be inherited.
  • Static class: A class containing only static members.
  • Inner class: An inner class is a class that is a member of another class.

In this tutorial, we will discuss each of these class types with examples.

We will also discuss some other types of classes that are considered special classes in Java.

  • Anonymous class: A class without any name.
  • Immutable class: A class whose object cannot be changed.
  • Singleton class: A class whose single instance can be created.
  • Object class: The base class of all Java features.
  • Wrapper class: Every primitive data type in Java has a wrapper class.

But first, let’s briefly discuss how to import a class in Java along with the Main class in Java that contains the main method or starting point in Java.

Import In Java

In Java, if we want to include any feature or functionality in our program, then we can use the “import” statement. Using import statement we can import an entire package and use its functionality in our program or we can also include a single class.

Given below is the syntax for the import statement.

import packageName/classname;

If we want to import java.lang package and all its classes, then we can write the following statement:

import java.lang.*;

Suppose we want to include the functionality of Arrays class in our program, then we can write the following statement:

import java.util.Arrays;

The import statement is equivalent to C/C++ include statement. The import statement is placed at the beginning of the Java program as the first statement. We can have more than one statement in the Java program.

Main Class In Java

We are already aware that in Java, the main () method is the starting point of any program execution and it can be placed in any class of that particular application. However, if we have a complex application with too many files and classes, then it is advisable to have a Main class and place the main () method in this Main class.

class Main{
		public static void main(String[] args){
			System.out.println(“Hello, World!”);
		}	
	}

Note that the JVM does not create an object of class Main. The logic behind this is that as main () is a static method, it can be called without any class object.

Types Of Classes In Java

Now let us move on to the types of classes in Java. We will explain each of these classes one by one followed by the programming examples.

#1) Concrete Class

A concrete class is any normal class in a Java program. This class will not have any abstract methods. All the methods in the concrete class are completely implemented.

A concrete class can inherit from another class, even an abstract class or implement an interface. We can instantiate the concrete class and create its objects.

A simple example of a concrete class is shown below.

public class Main { // Concrete Class example
   static int total(int val1, int val2) {
      return val1 + val2;
   }
   public static void main(String args[]) {
      int sum = total(100, 108);
      System.out.println("Total of two integers: " + sum);
   }
}

Output

output - Concrete Class

The above program shows a concrete class. We see that this class has a complete implementation. There is nothing left incomplete or unimplemented.

#2) POJO Class

A POJO (Plain Old Java Object) is a class containing only private member variables. Apart from the private member variables it only contains getter and setter methods used by these member variables.

A POJO class does not have its behavior. However, it may override some methods like equals or interfaces.

Properties of POJO class:

  • POJO class must have a public getter and setter method.
  • All the members or instance variables should be private.
  • POJO class does not extend or implement classes or interfaces that are pre-specified.
  • They do not contain annotations that are pre-specified.
  • Does not have a constructor without any arguments (no-argument constructor).

Given below is a Java Program that demonstrates the POJO class.

//declare a POJO class
class POJO_Class {
  private int daysOfWeek=7;         //private variable
  public int getdaysOfWeek() {      //getter
      return daysOfWeek;
   }
   public void setdaysOfWeek(int dow) {     //setter
      this.daysOfWeek = dow;
   }
}
public class Main {
   public static void main(String args[]){
      POJO_Class pojoDemo = new POJO_Class();   //instance of POJO class
      System.out.println("Days of the week:" + pojoDemo.getdaysOfWeek());
   }
}

Output

output - POJO class

The above demonstration of the POJO class shows that it has a private variable and the getter setter methods for this variable. To access this member variable, we use the getter method. The setter method is used to update the value.

#3) Abstract Class

An abstract class is a class that is incomplete or whose implementation is not completed. An abstract class cannot be instantiated. It needs to be extended by the other classes and implement its methods to form a concrete class.

An abstract class is declared by using the keyword ‘abstract’. An abstract class can have static and final methods as well as constructors.

Let’s demonstrate an abstract class in Java.

interface multiply              //interface multiply
{
int product(int num1, int num2);
}
// abstract class 
abstract class Product implements multiply
{
// this is an abstract method to calculate product of two numbers
public abstract int product(int num1, int num2);
}
// Concrete class :this will implement the abstract method above
class Main extends Product
{
public int product(int num1, int num2)
{
    return num1*num2;
}
// main method
public static void main(String args[])
{
Main obj = new Main();
int prod = obj.product(100, 20);
// print product
System.out.println("Product of two numbers: " + prod);
}
}

Output

output - Abstract class

In the above program, we have an interface multiply. We create an abstract class Product that implements a multiply interface. Inside the Product, we have a method product that is not implemented. Then we have a Main class that inherits the Product class and implements the product method. Later, we call this method on the Main class object.

#4) Static Class

A static in Java in general means the object that belongs to a class and not to the individual instances. So a static member or method in Java need not be accessed with an object but directly using a class name.

A static class in Java can contain only static members. Also, we cannot instantiate a static class.

The following Java program demonstrates a static class.

class Static_Class {
   static int total; // static variable
   static void sum(int val1, int val2) { // static method
        System.out.print("Static method to calculate sum:" + " ");
        total = val1 + val2;
        System.out.println(val1 + "+" + val2); // print the numbers
    }
   static class Nested_Class { // static class
      static { // static block
         System.out.println("static block inside a static nested class");
      }
      public void displaySum() {
         sum(25, 75); // call static method
         // print the value in static variable total, it holds the sum of two numbers
         System.out.println("Sum of two numbers:" + total); 
      }
   }
}
public class Main {
   public static void main(String args[]) {
       // declare static class object
      Static_Class.Nested_Class object = new Static_Class.Nested_Class(); 
      object.displaySum(); // call displaySum method inside a static class
   }
}

Output

output - Static Class

The above class demonstrates the static class. Here we have a static class that is a member of another concrete class. Inside the static class, we calculate the sum of two numbers and store the result in a static variable which is a member of the outer class.

#5) Final Class

A final class is a class that cannot be inherited or subclassed. Once a class is declared final in Java, it is a sort of constant and it becomes immutable.

Hence to make a class immutable, we have to declare it as final.

//final class
final class Base_Class {
   void Display() {
    System.out.println("Base_Class::Display()");
   }
}
//class Derived_Class extends Base_Class { //Compile-time error - can't inherit final class
 class Derived_Class{
   void Display() {
      System.out.println("Derived_Class::Display()");
   }
}
public class Main {
   public static void main(String[] arg) {
      Base_Class base_obj = new Base_Class();   //create a final class object
      base_obj.Display();
      Derived_Class deri_obj = new Derived_Class();
      deri_obj.Display();
   }
}

Output

output - Final Class

The above program first declares a Base_Class that is marked “final”. Hence when we try to extend it in Derived_Class, we get a compiler error. (The commented line). But we can create its object and call the Display method.

#6) Nested Class/ Inner Class

Nested class, also known as Inner class in Java is used to enhance encapsulation. A nested class/Inner class is a class enclosed inside another class.

Just like a class has variables and methods as its members, it can also have an inner class as its member.

A nested class has the following structure:

class OuterClass{
			class NestedClass{
				//nested class code…
			}
			//outerclass code…
		}	

Inner classes have the following subtypes:

  • Nested Inner class
  • Method Local Inner class
  • Anonymous Inner class
  • Static Nested class

#1) Nested Inner Class

A nested inner class has access to private member variables of an outer class. We can also apply access modifiers to the nested inner class.

#2) Method Local Inner Class

This is the inner class that is declared inside an outer class method.

#3) Anonymous Inner Class

Anonymous inner class is an inner class declared inside an outer class and is without any name.

#4) Static Nested Class

The way a class has a static member variable, it can also have a static class as its member.

An example of a Nested/Inner class is given below:

public class Main {
   //nested/inner class enclosed inside Main class.
   class InnerClass {
      public void inner_print() {
         System.out.println("Inner class");
      }
   }
   public static void main(String[] args) {
      System.out.println("Main in Outer class");
    }
}

Output

output - Nested Class/ Inner class

Other Special Classes In Java

Immutable Class In Java

An immutable class generates immutable objects. An immutable object is an object whose contents cannot be changed once the object is created. So an immutable class is the one whose object cannot be changed once created.

All the wrapper classes in Java for primitive types (Integer, Boolean, Byte, etc.) are immutable. The String class is also immutable.

We can also have user-defined immutable classes in Java.

For a class to be immutable, it needs to be declared final along with all its data members. Also, the class should have a parameterized constructor. All the member variables should have a getter method but not a setter method.

All the above requirements must be fulfilled for a class to be immutable.

Let’s implement a Java program to demonstrate the immutable class.

final class City
{ 
    final String city_name; 
    final int cityId; 
    //parameterised constructor
    public City(String name, int id) 
    { 
        this.city_name = name; 
        this.cityId = id; 
    } 
    //getters for member variables
    public String getcityName() 
    { 
        return city_name; 
    } 
    public int getcityId() 
    { 
        return cityId; 
    } 
} 
  
// Driver class 
class Main 
{ 
    public static void main(String args[]) 
    { 
        City city = new City("New York", 1001); 
        System.out.print("City Id:" + city.getcityId() + " ");
        System.out.println("City Name:" + city.getcityName()); 
          
        //city.cityId = 1002;    //cannot assign a value to final variable regNo 
    } 
}

Output

output - Immutable Class

In the above program, we have declared a City class. This is a final class and in this class, we have declared two member variables and a parameterized constructor. We have also declared getter methods for these two member variables. So the City class fulfills all the requirements of an immutable class.

Note the commented line of code in the main method. If we uncomment this line, then we will get a compiler error (provided in the comment here) as we are trying to set the value for a member variable.

Singleton Class In Java

A singleton class allows a single instance at a time. In Java, a singleton is a design pattern. This design pattern ensures that only one instance of a class exists at any point in time. So any class defined as a singleton has a single access point and it is global.

Note that termination of the application life cycle does not destroy a singleton class like the normal classes. When a class is declared singleton, then we do not create a new instance every time a new request for the object is made.

The same instance is used again and again. This way we can save the memory space mostly in case of multi-threaded and database applications.

We can use a singleton class for activities like caching, logging, etc.

The following program demonstrates a Singleton class.

  class Singleton  { 
    // static variable of type Singleton 
    private static Singleton single_instance = null; 
  
    // String variable 
    public String str; 
  
    // private constructor : restricted to this class 
    private Singleton() 
    { 
        str = "Singleton class::private constructor"; 
    } 
  
    // create instance of Singleton class using getInstance static method 
    public static Singleton getInstance()   { 
        if (single_instance == null) 
            single_instance = new Singleton(); 
  
        return single_instance; 
    } 
}
class Main 
{ 
    public static void main(String args[]) 
    { 
        // instantiate Singleton class with obj1
        Singleton obj1 = Singleton.getInstance(); 
  
        // instantiate Singleton class with obj2 
        Singleton obj2 = Singleton.getInstance(); 
  
        System.out.println("obj1(str):" + obj1.str); 
        System.out.println("obj2(str):" + obj2.str); 
        // change variable of instance obj1 
        obj1.str = (obj1.str).toUpperCase(); 
  
        System.out.println("\nAfter changing obj1(str):"); 
        System.out.println("obj1(str):" + obj1.str); 
        System.out.println("obj2(str):" + obj2.str); 
    } 
}

Output

output - Singleton Class in Java

In the above program, we have defined a singleton class with a private constructor. We have defined a member variable of String type. In the main method, we declare two instances of the singleton class. Then we change the String variable using one of the instances.

When we print the String value for both the instances, we notice that the String variable value has changed for both instances. Hence even though we changed the value only for one instance, because of the singleton class, changes are reflected in all the instances.

We always return the same instance even though we appear to create different instances.

Object Class In Java

The Object class is the parent class or the first class in Java. It is at the topmost level of the Java hierarchy.

As all the classes have the Object class as a superclass, all Java objects inclusive of Arrays implement the Object class methods. The object class is present in the “java.lang” package.

Declaration for java.lang.Object is:

public class Object

The following table describes the constructors and methods of Object class.

Constructor/MethodDescription
Object class constructor
Object()Object class constructor
Object class methods
protected Object clone()Returns a clone or copy of the object.
boolean equals(Object obj)Checks if a given object obj is equal to this object.
protected void finalize()Called by the garbage collector when all references to the object are destroyed.
Class getClass()Returns object’s runtime class.
int hashCode()Returns hash code for the object.
void notify()Use to wake up a single waiting thread.
void notifyAll()Wakes up all waiting threads.
String toString()Returns String equivalent of the object.
void wait()Makes a thread wait until it is woken up by notify method by another thread.
void wait(long timeout)Makes thread wait until time given by ‘timeout’ elapses or is woken up by notify or notifyAll methods.
void wait(long timeout, int nanos)Causes the thread to wait until the specified time has elapsed or until notify () or notifyAll () is invoked by another thread.

Let’s implement an example Java program that will demonstrate some of the Object class methods.

public class Main 
{ 
    public static void main(String[] args) 
    { 
        Main t = new Main(); 
        System.out.println("Main class Object HashCode:" + t.hashCode()); 
  
        t = null; 
  
        // call garbage collector  
        System.gc(); 
  
        System.out.println("Main class:End"); 
    } 
  
    @Override
    protected void finalize() 
    { 
        System.out.println("Main Class::finalize method called."); 
    } 
}

Output

output - Object Class

Here we have a Main class. In the main method () we create an object of Main class. This object is a descendent of Object class and supports all the Object class methods. Thus we use this object and call a few Object class methods like hashCode (), System.GC (), finalize () etc.

Wrapper Class In Java

Java provides a feature called wrapper class which has a mechanism that converts primitive data type into object and vice versa. Wrapper classes are the classes that represent primitive types like int, char, etc. as objects.

Thus each primitive data type in Java has its corresponding wrapper class.

The following table shows the primitive data types and their equivalent wrapper class.

Primitive typeWrapper type
booleanBoolean
charCharacter
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble

To convert the primitives into objects and objects into primitives, we have techniques called “autoboxing” and “boxing” respectively. Ase Java is an Object-oriented programming language, we always deal with objects, and we also have lots of features like Collections, serialization, etc. that also need objects and primitive types.

So it’s imperative that we always need objects and primitive types in Java and thus we require these techniques of autoboxing and unboxing.

Autoboxing

Autoboxing is a technique of automatically converting a primitive data type to an object of its corresponding wrapper class. For example, conversion of int to Integer class, char to Character class, etc. are instances of autoboxing.

Note: Wrapper classes use the valueOf () method to convert the primitive into objects which are depreciated since Java 5.

Unboxing

The reverse conversion of wrapper class objects into their corresponding primitive data types is called “unboxing”.

Note: Since Java 5, the method intValue () that converts the wrapper object into a primitive type is depreciated.

Given below is an example of boxing/unboxing.

public class Main {  
    public static void main(String args[]){  
    //Convert int to Integer : boxing 
    int num=20;  
    Integer int_class=  Integer.valueOf(num);//explicit conversion from int to Integer   
    Integer inum=num;//autoboxing  
    System.out.println("int => Integer: " + num+" => "+inum);  
        
    //Convert Integer to int: unboxing    
    Integer val=new Integer (3);    
    int ival=val.intValue();//explicit conversion from Integer to int  
    int jval=val;//unboxing    
    
    System.out.println("Integer => int:" + val+" => "+jval); 
    }
}  

Output

output - Wrapper Class

The above program shows autoboxing and unboxing on int value. First, we convert int to Integer object and then an Integer object is converted to the int data type.

Let’s implement a program that demonstrates the wrapper classes present in Java.

public class Main {  
    public static void main(String args[])  {  
        byte bbyte=10;  
        short sshort=20;  
        int iint=300;  
        long llong=400;  
        float ffloat=3.14F;  
        double ddouble=77.2D;  
        char cchar='A';  
        boolean bboolean=true;  
  
        //Convert primitives into objects => Autoboxing 
        Byte byteobj=bbyte;  
        Short shortobj=sshort;  
        Integer intobj=iint;  
        Long longobj=llong;  
        Float floatobj=ffloat;  
        Double doubleobj=ddouble;  
        Character charobj=cchar;  
        Boolean boolobj=bboolean;  

         //Print converted objects  
        System.out.println("Primitives converted to Objects:");  
        System.out.println("Byte object: "+byteobj);  
        System.out.println("Short object: "+shortobj);  
        System.out.println("Integer object: "+intobj);  
        System.out.println("Long object: "+longobj);  
        System.out.println("Float object: "+floatobj);  
        System.out.println("Double object: "+doubleobj);  
        System.out.println("Character object: "+charobj);  
        System.out.println("Boolean object: "+boolobj);  
  
        //Convert Objects to Primitives => Unboxing 
        byte bytevalue=byteobj;  
        short shortvalue=shortobj;  
        int intvalue=intobj;  
        long longvalue=longobj;  
        float floatvalue=floatobj;  
        double doublevalue=doubleobj;  
        char charvalue=charobj;  
        boolean boolvalue=boolobj;  
  
        //Print primitives  
        System.out.println("Converting Objects to Primitives");  
        System.out.println("byte value: "+bytevalue);  
        System.out.println("short value: "+shortvalue);  
        System.out.println("int value: "+intvalue);  
        System.out.println("long value: "+longvalue);  
        System.out.println("float value: "+floatvalue);  
        System.out.println("double value: "+doublevalue);  
        System.out.println("char value: "+charvalue);  
        System.out.println("boolean value: "+boolvalue);  
    }
} 

Output

output - Boxing and Unboxing

The above program output shows the conversion from primitive types to wrapper objects (Autoboxing) and reverses conversion from wrapper objects to primitive types (unboxing).

Frequently Asked Questions

 Q #1) What is the Class Data type in Java?

Answer: Java provides a class named “Class” that contains information about all the classes, objects, and interfaces of the running application. The Class class also represents primitive data types and the void type.

The Class class is a part of the java.lang package.

Q#2) What is the Normal Class in Java?

Answer: A normal class in Java is a non-static class. We can create objects of a normal class using the new keyword. Also, any normal class can have another class as its member. In this case, the member class is called nested or inner class and the enclosing class is called outer class.

Q #3) Is String a Wrapper Class in Java?

Answer: No, String is not a wrapper class in Java. For a class to be a wrapper class, we need its corresponding primitive type. For example, for Integer wrapper class we have primitive type int. For the String class, we do not have a corresponding primitive data type.

Q #4) What is the benefit of Wrapper Class?

Answer: Wrapper classes are used for the conversion of primitive data types to objects. In other words, wrapper classes wrap primitive types into objects. Wrapper classes are used when certain Java features like Collections only expect objects and not primitive data types.

Q #5) Why is Singleton Class used in Java?

Answer: Whenever we want a global point of access for a particular object, we go for a singleton pattern that allows us to design a singleton class in which there will be only one instance. Singleton classes are used in caches, thread pooling, database applications, logging, etc.

Conclusion

In this tutorial, we have covered the various class types used in Java. We saw the concrete, abstract, final, static, Nested, POJO, etc. class types. Apart from this, we also discussed Singleton classes, Immutable classes, and discussed their implementation examples too.

We also covered wrapper classes and object classes in Java. Wrapper classes are the classes that wrap the primitive data types of Java into objects. Object class in Java is the superclass of all the other classes. It is the topmost class in the Java hierarchy.

Now that we have discussed the classes and objects in Java and the class types, in the next tutorial we will proceed with a detailed discussion on constructors in Java.

=> Check Out The Perfect Java Training Guide Here.