Quick Refresh of OOP In JAVA

This article serves as a comprehensive and concise review of key object-oriented programming (OOP) concepts in Java. It provides a quick revision for those already familiar with OOP principles, enabling them to refresh their knowledge efficiently. By offering a concise summary of these concepts, the blog facilitates a professional-level revision, ensuring that readers can reinforce their understanding of OOP principles in Java promptly and effectively.

In this article, we will cover the following terminologies with a detailed explanation and source code

  1. Classes

  2. Objects

  3. Constructor

  4. Modifiers

  5. Packages

  6. New Keyword

  7. This Keyword

  8. Static and Non-Static

  9. Inheritance

  10. Super Keyword

  11. Encapsulation

  12. Abstraction

  13. Polymorphism

  14. Interface

  15. Overloading

Object-oriented Programming

OOP stands for Object-Oriented Programming. It is a programming paradigm that organizes code into reusable objects that contain both data and methods (functions) to manipulate that data

Object-oriented programming has several advantages over procedural programming:

  • OOP is faster and easier to execute

  • OOP provides a clear structure for the programs

  • OOP helps to keep the Java code DRY “Don’t Repeat Yourself”, and makes the code easier to maintain, modify and debug

  • OOP makes it possible to create fully reusable applications with less code and shorter development time

Classes And Objects

In object-oriented programming (OOP), a class serves as a blueprint or template for creating objects, while an object represents a specific instance of a class.

To gain a deeper understanding, let us break down the provided statement into smaller components. Firstly, it is crucial to grasp the meaning of "instance" in simpler terms.

According to Google, an instance refers to an example or a single occurrence of something. In other words, an instance can be thought of as another term for an example.

Therefore, a class is a template or a design, whereas an object is the actual tangible representation of that class. Consequently, we can state that a class is a template, while an object is an instance of a class.

Distinctions Between A Class And An Object:

Additionally, we can elucidate several other distinctions between a class and an object:

  1. Classes exist conceptually and do not possess a physical existence, whereas objects are actual entities.

  2. Objects occupy memory resources, specifically the Random Access Memory (RAM), whereas classes do not consume memory directly.

Example:

Look at the following illustration to see the difference between class and objects:

Difference Between Class and Object

Picture source: W3 School

When the individual objects are created, they inherit all the variables and methods(Functions) from the class. When you declare an object of a class, you are creating an instance of that class. Thus, a class is a logical construct. An object has physical reality.

Object

To create an object in Java using OOP, we have to follow 3 steps

  1. Define a class

  2. Instantiate the object:

  3. Access the object methods and properties

Class Attributes

  • Class attributes are variables that are defined within a class and are shared by all instances of that class. They are typically defined at the top level of a class, outside of any method.

  • Class attributes are accessed using the class name followed by the attribute name, or through an instance of the class.

  • They can be accessed and modified by all instances of the class, as well as by class methods and the class itself and changes made to a class attribute are reflected across all instances of the class.

class Cars{
    // Properties/Attributes of a Object
    int price;
    String name;
    String color;
}

calling it in Main.java

public class Main {
    public static void main(String[] args) {
      Cars car1 = new Cars(1000, "BMW", "Black"); // Object with parameters
       System.out.println(car1.color); // Accessed object property i.e color
    }
}

Methods

  1. Methods in object-oriented programming (OOP) are functions defined within a class that perform specific actions or operations on objects.

  2. Methods are defined inside a class and they can perform various operations, such as modifying object state, performing calculations, or interacting with other objects.

  3. Methods are invoked by calling them on an instance of a class using dot notation.

  4. They can take parameters as input and return values as output.

public class Main {
    public static void main(String[] args) {
      Cars car1 = new Cars(1000, "BMW", "Black"); // Object with parameters
       car1.setPrice(2000); // Accessed object method (function) and setting the price
       car1.getPrice(); // Accessed object method (function) and get the price
    }
}
class Cars {
        // simple method
        void start() {
            System.out.println("Starting the car");
         }
        // Setter Method
        void setPrice(int price) {
            this.price = price;
        }

        // Getter Method
        void getPrice() {
            System.out.println(price);
        }
}

Constructor

  • Constructor is a special type of method that has the same name as the class

  • Constructor is used to initialize the object

  • Constructor is called when the object is created

  • The constructor does not have a return type

  • Constructor can be overloaded

  • Constructor can be private, public, protected or default

  • If you don't create a constructor, the compiler will create a default constructor for you

  • If you create a constructor with parameters, you will have to create a constructor without parameters as well

    // Constructor with parameters
    Cars(int price, String name, String color) {
        this.price = price;
        this.name = name;
        this.color = color;
    }

    // Constructor with parameters an object
    Cars(Cars singleObjCars) {
        this.price = singleObjCars.price;
        this.name = singleObjCars.name;
        this.color = singleObjCars.color;
    }

    // Constructor without parameters
     Cars(){
        System.out.println("This is constructor without parameters");
     }

    // Calling a constructor from another constructor
    Cars() {
        this(13, "Yaris", "white");
    }
  Cars car1 = new Cars(1000, "BMW", "Black"); // Object with parameters

here, Cars(1000, "BMW", "Black") is a constructor.

Overloading

In Java, it is possible to define two or more methods, and constructors within the same class that share the same name, as long as their parameter declarations are different. While overloaded methods may have different return types, the return type alone is insufficient to distinguish two versions of a method. When Java encounters a call to an overloaded method, it simply executes the version of the method whose parameters match the arguments used in the call.

// Constructor with parameters
Cars(int price, String name, String color) {
        this.price = price;
        this.name = name;
        this.color = color;
}
// Constructor without parameters
Cars() {
   System.out.println("This is constructor without parameters");
}

In the above example, Car is a function that repeats two times with different parameters. Here, this overloading is also known as constructor overloading.

This Keyword

Sometimes a method will need to refer to the object that invoked it. To allow this, Java defines this keyword. this can be used inside any method to refer to the current object. That is, this is always a reference to the object on which the method was invoked.

 Cars car1 = new Cars(1000, "BMW", "Black");
Cars(int price, String name, String color) {
        this.price = price;
        this.name = name;
        this.color = color;
}

Here this will replace the object name. i.e. car1, so, during run time, this will replace car1.price, car1.name and so on.

New Keyword

In Java, the "new" keyword is used to create an instance or object of a class. It is an essential keyword in object-oriented programming (OOP) for instantiating classes and allocating memory for objects. Here are some key points about the "new" keyword in Java:

  • The "new" keyword is commonly used in Java to create instances of classes for various purposes, such as storing data, invoking methods, or accessing class members.

  • The syntax for creating a new instance is: ClassName objectName = new ClassName();

  • The "new" keyword dynamically allocates memory for the object on the heap.

  • Each time "new" is used, a unique object with its own memory space is created.

Packages

A package in programming refers to a way of organizing related classes, functions, and other code components into a single unit. In simple words, Packages are containers for classes. They are used to keep the class namespace compartmentalized. The package is simply a folder name

For example, a package allows you to create a class named List, which you can store in your own package without concern that it will collide with some other class named List stored elsewhere.

  • A package acts as a container or directory that holds related code files.

  • When a package is imported, only those items within the package declared as public will be available to non-subclasses in the importing code.

  • Packages provide a way to avoid naming conflicts by encapsulating code within their own namespace.

  • Packages often have a hierarchical structure, where sub-packages can be nested within parent packages, forming a tree-like organization.

  • Packages typically follow a naming convention, often based on the project or organization's domain name in reverse order (e.g., com.example.project.package).

package com.maham.introduction

the file needs to be stored in com\maham\introduction in a Windows environment. Be sure to choose your package names carefully. You cannot rename a package without renaming the directory in which the classes are stored.

Access Modifier

In Java, access modifiers are keywords used to control the visibility and accessibility of classes, methods, variables, and constructors. They determine whether other parts of the code can access and use these elements

Picture source: Starter Tutorials

The above picture perfectly explains the access modifier in Java.

Final Keyword

In Java, the "final" keyword is used to define a constant value, prevent inheritance, or make a method unchangeable. In Java, the "final" keyword, when used with primitive data types, enforces immutability by making the value constant. This means that once a "final" variable is assigned a value, it cannot be modified. However, when "final" is used with reference types, it ensures that the reference remains constant, but the internal state of the object can still be changed.

final int x = 5; // A final variable of primitive type
// x = 10; // Error: Cannot modify the value of a final variable
final Cars finalCar = new Cars(); // A final reference variable
finalCar.setPrice(45); // Modifying the internal state of the object is allowed
// finalCar = new Cars(); // Error: Cannot assign a new reference to a
// final variable

Static and Non-Static

In Java OOP, the terms "static" and "non-static" are used to differentiate between class-level members and instance-level members.

Static

  • Static members belong to the class itself rather than individual instances of the class.

  • When a member is declared static, it can be accessed before any objects of its class are created, and without reference to any object. You can declare both methods and variables to be static.

  • A static method can access only static data. It cannot access non-static data (instance variables)

  • A static method can call only other static methods and cannot call a non-static method from it.

  • A static method can be accessed directly by the class name and doesn’t need any object.

  • A static method cannot refer to "this" or "super" keywords in any way

public class Human {
    int age;
    static long population;

    static void message() {
        System.out.println("Hello world");
//        System.out.println(this.age); // cant use this over here
    }

    public Human(int age, String name, int salary, boolean married) {
        this.age = age;
        Human.population += 1; // directly refers to class thats why we are not using this keyword
    }
}

Non Static

  • Non-static members are associated with individual instances of the class.

  • Each instance of the class has its own copy of non-static members.

  • A non-static member belongs to an instance. It's meaningless without somehow resolving which instance of a class you are talking about.

public class Main {
    public static void main(String[] args) {
        Main funn = new Main();
        funn.fun2();
    }

    // this is not dependent on objects
    static void fun() {
        // greeting(); // you cant use this because it requires an instance
        // but the function you are using it in does not depend on instances

        // you cannot access non static stuff without referencing their instances in
        // a static context

        // hence, here I am referencing it
        Main obj = new Main();
        obj.greeting();
    }

    void fun2() {
        greeting();
    }

    // we know that something which is not static, belongs to an object
    void greeting() {
        // fun();
        System.out.println("Hello world");
    }
}

Inheritance

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows one class to inherit the properties and behaviours of another class. inheritance concept can be categorized into two concept

  • subclass (child) - the class that inherits from another class

  • superclass (parent) - the class being inherited from

To inherit from a class, use the extends keyword.

class Vehicle {
    private String brand;
    private int year;

    public Vehicle(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    public void startEngine() {
        System.out.println("Starting the engine of the vehicle...");
    }
}

class Car extends Vehicle {
    private int numberOfDoors;

    public Car(String brand, int year, int numberOfDoors) {
        super(brand, year);
        this.numberOfDoors = numberOfDoors;
    }

    public void accelerate() {
        System.out.println("Accelerating the car...");
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car("Toyota", 2022, 4);
        myCar.startEngine();  // Inherited from Vehicle class
        myCar.accelerate();   // Car-specific method
    }
}

Super, Override Keyword and Polymorphism

Super Keyword

The super keyword refers to superclass (parent) objects. It is used to call superclass methods and to access the superclass constructor.

Override Keyword

Method overriding is a feature that allows a subclass to provide a different implementation for a method that is already defined in its superclass. Method overriding enables a subclass to define its own behaviour while still maintaining the same method signature as the superclass.

Polymorphism

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance.

Polymorphism is achieved through inheritance and method overriding. When a superclass reference variable is used to refer to a subclass object, polymorphism comes into play.

class Vehicle {
    public void startEngine() {
        System.out.println("Starting the engine of the vehicle...");
    }
}

class SportsCar extends Car {
    @Override
    public void startEngine() {
        super.startEngine();  // Calling the overridden method in the immediate superclass
        System.out.println("Starting the engine of the sports car...");
    }
}

public class Main {
    public static void main(String[] args) {
        SportsCar sportsCar = new SportsCar();
        sportsCar.startEngine();
    }
}

Abstract Class

In object-oriented programming, there are cases where you need to create a superclass that defines a generalized form to be shared by its subclasses while leaving the specific implementation details to each subclass.

To achieve this, Java provides a solution in the form of abstract methods. Abstract methods are methods that must be overridden by the subclass in order for the subclass to have any meaningful functionality. By specifying the abstract modifier, you can require that certain methods be overridden by subclasses.

abstract class Car {
    private String brand;
    private String model;

    public Car(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public abstract void start();

    public abstract void stop();
}

class SportsCar extends Car {
    public SportsCar(String brand, String model) {
        super(brand, model);
    }

    @Override
    public void start() {
        System.out.println(getBrand() + " " + getModel() + " is starting like a powerful sports car.");
    }

    @Override
    public void stop() {
        System.out.println(getBrand() + " " + getModel() + " is stopping like a sports car.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car sportsCar = new SportsCar("Ferrari", "488 GTB");
        sportsCar.start();
        sportsCar.stop();
    }
}

Interface

An interface in Java is a collection of abstract methods that define a contract for classes to adhere to. It specifies a set of methods that must be implemented by any class that implements the interface. In addition to abstract methods, interfaces can also include constant variables.

Moreover, Multiple inheritances is not available in Java. (Same functions in 2 classes it will skip that hence no multiple inheritances). The problem with MULTIPLE INHERITANCE is that two classes may define different ways of doing the same thing, and the subclass can't choose which one to pick.

Engine.java

public interface Engine {
    static final int PRICE = 78000;
    void start();
    void stop();
    void acc();
}

Media.java

public interface Media {
    void start();
    void stop();
}

Car.java

public class Car implements Engine,Media{

    int a = 30;
    @Override
    public void start() {
        System.out.println("I start engine like a normal Car");
    }

    @Override
    public void stop() {
        System.out.println("I stop engine like a normal Car");
    }

    @Override
    public void acc() {
        System.out.println("I accelerate like a normal Car");
    }
}

Abstract and Encapsulation

Abstract: Abstract is like a special type of class that doesn't have a complete form on its own. It's like a plan or a blueprint for other classes to follow. It tells other classes what methods they should have, but it doesn't give them the exact details of how those methods should work. It's a bit like a puzzle piece that fits into different places and completes a bigger picture when combined with other pieces.

Encapsulation: Encapsulation is like putting things in separate boxes to keep them safe and organized. In programming, it means grouping together related information and functions into a single box called an object. This helps to organize the code and protect the data inside the object. Encapsulation also means that we can control how other parts of the code interact with the object. We can have some things inside the object that are only accessible from the outside in a certain way, like pressing a button or asking nicely.

So, the abstract is about creating a plan or blueprint for classes to follow, while encapsulation is about organizing and protecting data and functions inside objects.

Conclusion

In conclusion, this blog provided a quick revision of OOP concepts in Java. It covered classes, objects, constructors, modifiers, packages, the new keyword, the this keyword, static and non-static, inheritance, the super keyword, encapsulation, abstraction, polymorphism, interfaces, and overloading. It serves as a handy reference for reviewing these fundamental concepts in Java OOP programming.