Learn OOPs Concept in Java with examples

OOPs stands for Object-Oriented Programming system.

Java was initially built to follow the Object-Oriented approach. From the Java version, 1.8 functional programming was introduced. Now a Java developer can follow both object-oriented as well as functional approaches. If you want to know about functional Programming in-depth please check this link on functional programming. Coming back as part of this article we will focus on OOPs concepts in java.

What is Object-Oriented Programming In Java ?

It is a Programming approach that deals with objects. These Objects are real-world entities. Anything surrounding you is an object. Ex: The Laptop you are working on now is an object. The Chair you are sitting on is an Object etc.

Prerequisite terms

We should know these basic terms before learning the OOPs Concepts :

Class

Class is a structure that we create to depict a real-world entity. Ex: Painting of a person. Painting just shows how a person looks like but it is not the actual person. Below we are creating a BankAccount class.

public class BankAccount {

  int accountNumber;

  String accountName;

  String accountStatus;

  public int getAccountNumber() {
    return accountNumber;

  }

  public String getAccountName() {
    return accountName;

  }

  public String getAccountStatus() {
    return accountStatus;

  }

  public void setAccountNumber(int accountNumber) {
    this.accountNumber = accountNumber;

  }

  public void setAccountName(String accountName) {
    this.accountName = accountName;

  }

  public void setAccountStatus(String accountStatus) {
    this.accountStatus = accountStatus;

  }

  @Override

  public String toString() {

    return "BankAccount [accountNumber=" + accountNumber + ", accountName=" + accountName + ", accountStatus=" + accountStatus + "]";

  }
}

Object

The object is an entity having some properties and states. An Instance of a Class is an object.

In the above example, we have created a BankAccount prototype. We cannot make use of that Bank-Account class until we create an Object for that class.

We can create an object of a class using a new keyword. Once we create an object memory will be allocated to the properties of that object. These properties can be referred to using the object-name.

Say we create a BankAccount Object. The Properties of a BankAccount are AccountNumber, AccountName, AccountStatus to which the memory will be allocated.

The State depends on the property’s value. If the property value changes then it means the state of the object is changed. Ex: AccountStatus can be Active Or In-Active. If the AccountStatus is In-Active then it means the BankAccount State is In-Active.

If we change the AccountName of a BankAccount from “Suraj” to “Surya” then it means the state of the BankAccount Object is changed.

public class Demo {

  public static void main(String[] args) {

    BankAccount bankAccount = new BankAccount();

    bankAccount.setAccountName("Suraj");
    bankAccount.setAccountNumber(12345678);
    bankAccount.setAccountStatus("Active");
    System.out.println(bankAccount);
  }
}

BankAccount bankAccount = new BankAccount()

We can create the BankAccount Object using new keyword . And the BankAccount object is referred using the reference variable “bankAccount” .

OOPs java concepts

  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism

Encapsulation

Encapsulation means the binding of variables and methods together in a single unit . We can achieve encapsulation in Java using a class . A class is responsible to hold the variables and methods together .

Benefits of encapsulation

  1. We can hide variables of a class from other classes using encapsulation . For achieving encapsulation we have to mark the variables as private. This hidden variables can be accessed in other classes using the public getters and setters methods.
  2. We can use Setter method to update the value of the variable and Getter method to retrieve the value of the variable .
  3. We can use Getters and Setters methods for additional validations and error handling. This helps to keep our code more secure by restricting others from using our code in their own way.
  4. Encapsulation also helps to achieve Loose Coupling. It means dependency between the modules or the classes should be low. We should always try to lower the dependency between classes because this lowers the risk of any behavioural manipulation.

Ex: We have to register a user whose age is above 35.

Without encapsulation : We will mark the variables as public and any other class can modify our variables .

public class User {

  public String name;

  public int age;

  @Override
  public String toString() {
    return "User [name=" + name + ", age=" + age + "]";
  }
}

public class Demo {

  public static void main(String[] args) {

    User user = new User();

    user.name = "Suraj";
    user.age = 30;

    System.out.println(user);

  }
}

Output: User[name = Suraj, age = 30]

Note* In the above example developer of the User class has no control over its properties. Even though the User class was created to add users whose age is above 35 but still, the Demo class have added a User with age 30 ( Behaviour is changed )

With encapsulation : We can mark the variables as private and add a validation logic in the setter method. So that we can only register users with an age greater than 35 .

public class User {

  private String name;

  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {

    if (age <= 35) {
      throw new IllegalArgumentException("Age should be greater than 35");
    }

    this.age = age;
  }

  @Override
  public String toString() {
    return "User [name=" + name + ", age=" + age + "]";
  }
}

public class Demo {

  public static void main(String[] args) {

    User user = new User();

    user.setName("Suraj");
    user.setAge(30);

    System.out.println(user);

  }
}

Output: Exception in thread "main"
java.lang.IllegalArgumentException: Age should be greater than 35

Note* Here Demo class will not be able to add a user if the user’s age is less than 35. Hence no behaviour is changed. Thus encapsulation helps to achieve loose coupling )

Abstraction

It is a process of hiding the low-level details and showing only the essential information. It means we will know how to perform an operation but we will not know the underlying details like how that operation is performed.

Ex : When we click some key on a keyword it reflects on the screen. Here we are not aware of how pressing a button changes something on our screen. The background process is hidden from users.

We can achieve abstraction in Java using Abstract class and Interfaces.

Abstract class

  1. If we declare a class using abstract keyword it is known as abstract class.
  2. Abstract class can contain abstract methods as well as concrete methods. Abstract methods have no implementation.
  3. The methods which are defined as abstract in superclass should be implemented in the subclass ( If the subclass is not abstract )
  4. We cannot instantiate a abstract class, means we cannot create an object of abstract class.
  5. Abstract class can have parameterized constructors so as to initialize the variables of that class.
abstract class Database {

  void genericCode() {
    System.out.println("This piece of code is required by all databases");
  }

  abstract void connectDatabase();
}

class OracleDB extends Database {
  @Override
  void connectDatabase() {
    System.out.println("Connecting to Oracle database");
  }
}

class MySQLDB extends Database {
  @Override
  void connectDatabase() {
    System.out.println("Connecting to MySQL database");
  }
}

class HigherLevelDetails {
  Database database;

  HigherLevelDetails(Database database) {
    this.database = database;
  }

  void connect() {
    database.genericCode();
    database.connectDatabase();
  }
}

public class Demo {

  public static void main(String[] args) {

    HigherLevelDetails higherLevelDetails = new HigherLevelDetails(new OracleDB());

    higherLevelDetails.connect();
  }
}

Output : This piece of code is required by all databases
         Connecting to Oracle database

Note* HigherLevelDetails class shows the higher level details. It just says I am having a Database , please pass an reference of Implemented Database. HigherLevelDetails class can have a reference of OracleDB as well as MySQLDB. HigherLevelDetails class don’t show the lower level details.

If you want to go in more depth of abstract class please refer this link Abstract class

Interface

It is a bridge or connectivity between high-level Components and low-level components just like an abstract class. The difference is abstract classes can have abstract methods and concrete methods. On the other hand, interfaces just have abstract methods. So we can say interface helps to achieve 100% abstraction whereas abstract class do not provide complete abstraction.

  1. All the methods in interface are abstract prior to Java 8.
  2. Interface do have constructors.
  3. Methods in interface are by default abstract and public. So that it can implemented in other class or package.
  4. Variables in interface are by default public, static and final.
interface IDatabase {
  abstract void connectDatabase();
}

class OracleDBImpl implements IDatabase {
  @Override
  public void connectDatabase() {
    System.out.println("Connecting to Oracle database");
  }
}

class MySQLDBImpl implements IDatabase {
  @Override
  public void connectDatabase() {
    System.out.println("Connecting to MySQL database");
  }
}

class HigherLevelDetailsImpl {
  IDatabase database;

  HigherLevelDetailsImpl(IDatabase database) {
    this.database = database;
  }

  void connect() {
    database.connectDatabase();
  }
}

public class InterfaceDemo {

  public static void main(String[] args) {

    HigherLevelDetailsImpl higherLevelDetails = new HigherLevelDetailsImpl(new OracleDBImpl());

    higherLevelDetails.connect();
  }
}

Output : Connecting to Oracle database

Note* HigherLevelDetailsImpl class just shows the higher level details. It just says I am having a Database, please pass an reference of Implemented Database and make use of it. HigherLevelDetailsImpl class can have a reference of OracleDBImpl as well as MySQLDBImpl. HigherLevelDetailsImpl class don’t show the lower level details.

If you want to go in more depth of interface please refer this link Interface

Inheritance

Acquiring some characteristics from parent class is known as Inheritance. Ex : You can have eyes like your mom, hair like your dad . It means you have acquired some properties from your parents. In the same way, a subclass can inherit properties from the superclass.

Inheritance is termed as IS-A Relationship . Ex: Elephant class IS-A child of Animal class.

Benefits of Inheritance

  1. Code Reuse – Subclass can use the Superclass properties. Hence Subclass don’t have to write extra piece of code and can reuse the existing code.
  2. Less developement and saves time – As we can reuse the code hence developer has to write less piece of code which eventually saves time as well.
  3. Reliability – As the Subclass uses some existing piece of code from Superclass hence we can trust the existing piece of code because it will be already tested using some unit test cases or functional test cases.
  4. Code Extensibility – N number of Subclasses can inherit a Superclass. Ex: Animal class can be inherited by Tiger class or Lion class or Elephant class etc.

extends keyword is use to inherit a class.

implements keyword is use to inherit an interface.

Types of Inheritance

Single level inheritance: A single class can inherit another class. It is a single-level chain.

class Father {
  void fathersMoney() {
    System.out.println("Money earned by Father");
  }
}

class Son extends Father {
  void sonsMoney() {
    System.out.println("Money earned by Son");
  }
}

class Daughter extends Father {
  void daughtersMoney() {
    System.out.println("Money earned by Daughter");
  }
}

public class InheritanceDemo {
  public static void main(String[] args) {
    Son son = new Son();
    son.sonsMoney();
    son.fathersMoney();

    Daughter daughter = new Daughter();
    daughter.daughtersMoney();
    daughter.fathersMoney();
  }
}
 

Output :  Money earned by Son
          Money earned by Father
          Money earned by Daughter
          Money earned by Father

Note* In the above example Son extends Father; Daughter extends Father . A Subclass is extending a Superclass, hence it is a Single level inheritance.

Father -> Son

Father -> Daughter

Son and Daughter both are having access to Father’s Money. We can say Father’s money is inherited by Son and Daughter, this concept is known as inheritance .

Multi-Level Inheritance : It is a chain of Inheritance.

class GrandFather {
  void grandFathersMoney() {
    System.out.println("Money earned by GrandFather");
  }
}

class Father extends GrandFather {
  void fathersMoney() {
    System.out.println("Money earned by Father");
  }
}

class Son extends Father {
  void sonsMoney() {
    System.out.println("Money earned by Son");
  }
}

public class InheritanceDemo {
  public static void main(String[] args) {
    Son son = new Son();
    son.sonsMoney();
    son.fathersMoney();
    son.grandFathersMoney();
  }
}

Output : Money earned by Son
         Money earned by Father
         Money earned by GrandFather

GrandFather -> Father -> Son

Father inherit properties from GrandFather. Son inherit properties from Father. Hence Son have access to Father’s Money as well as GrandFather’s Money. This is a multi level inheritance .

Multiple Inheritance : Inheriting properties from more than one Parent class. It is not possible to achieve multiple inheritance using java classes .

Say Father and Uncle are 2 Classes. Ex : Son extends Father , Uncle

It is not possible . A child cannot inherit money from both Father and Uncle . It will be a ambiguity problem .

class Father {
  void money() {
    System.out.println("Money earned by Father");
  }
}

class Uncle {
  void money() {
    System.out.println("Money earned by Father");
  }
}

class Son extends Father, Uncle {

}
 
Output : Not possible

Note* Father and Uncle both are having money method. If a Son extends both Father and Uncle then which money method Son will get thats an ambiguity. Hence Java don’t support Multiple Inheritance with Class.

We can achieve multiple inheritance in Java using an interface. Methods in interface are abstract hence they don’t have a implementation of there own hence the implementor class has to give a definition to those methods.

interface Father {
  void money();
}

interface Uncle {
  void money();
}

class Son implements Father, Uncle {
  @Override
  public void money() {
    System.out.println("Son earns his own money");
  }
}

public class InheritanceDemo {
  public static void main(String[] args) {
    Son son = new Son();
    son.money();
  }
}

Output : Son earns his own money

Note* In the above example money method is present in Father interface as well as the Uncle interface. But those methods do not have any implementation hence the Subclass Son will not be confused on which parent method to use because both are empty. Hence Son class can provide a implementation to that method on its own. Thus Multiple inheritance is achieved in java using Interfaces .

Polymorphism

One name multiple forms . Say we have to write a word “Java” in the notebook. So i will write Java in my own handwriting, you will be writing in your own. So the word is common but we are writing it in multiple forms. This is polymorphism.

Java has provided interface for JDBC Connectivity. Oracle implements that interface in there own way for providing connectivity to the Oracle database. MySQL implements that interface in there own way for providing connectivity to the MySQL database.

So we can think polymorphism as doing a single action in multiple ways.

Types of polymorphism

Compile time polymorphism or Static polymorphism: A call to a method is resolved at compile time. We can achieve compile time polymorphism using method overloading.

Method Overloading means there can be multiple methods in a class with same name but with different arguments. It also means method signature will be different. Hence we will know which method will be called at compilation time.

class AdditionOperation {
  int addition(int a, int b) {
    return a + b;
  }

  int addition(int a, int b, int c) {
    return a + b + c;
  }
}

public class CompileTimePolymorphism {

  public static void main(String[] args) {

    AdditionOperation operation = new AdditionOperation();

    System.out.println("Two numbers are added : " + operation.addition(5, 10));

    System.out.println("Three numbers are added : " + operation.addition(5, 10, 20));
  }
}

Output : Two numbers are added : 15
         Three numbers are added : 35

Run time polymorphism or Dynamic polymorphism: A call to a method is resolved at runtime. We can achieve run time polymorphism using method overriding .

We can achieve Method Overriding at the hierarchical level or at the time of inheritance ( Superclass and Subclass ). Method Signature in the Subclass will be the same as method signature in the Superclass. Since the method signatures are same hence we will not know which method is being called at compile time and that will get resolved at runtime.

class Database {
  void connectDatabase() {
    System.out.println("Connect to generic databse");
  }
}

class OracleDB extends Database {
  void connectDatabase() {
    System.out.println("Connect to Oracle databse");
  }
}

public class RuntimePolymorphism {

  public static void main(String[] args) {

    Database database = new OracleDB();

    database.connectDatabase();
  }
}

Output : Connect to Oracle databse

Note* connectDatabase is the method with same signature in Subclass as well as Superclass. Here we can see OracleDB Subclass has overridden connectDatabase method of Database Superclass. So its not possible to guess which connectDatabase method will be called at compile time hence its being resolved at runtime. In the above case, we are passing the OracleDB object as a Database reference hence OracleDB connectDatabase method gets called .

In this article we have covered the OOPS Concepts in Java . I hope you found this article interesting and valuable . Please share this article with your friends and help me grow as a blogger . If you are having any concern or questions on this article please comment below . If you want to get in touch with me please visit the Contact me page and send me a email .