Progress5 of 14 topics

36% complete

Object-Oriented Programming in Java

Object-Oriented Programming (OOP) is a programming paradigm that uses "objects" to design applications. In this tutorial, you'll learn the core concepts of OOP in Java and how to implement them in your programs.

What is Object-Oriented Programming?

Object-Oriented Programming (OOP) is a programming approach that organizes software design around objects rather than functions and logic. An object is a self-contained unit that contains data (attributes) and procedures (methods) that operate on that data.

Java is a primarily object-oriented language, which means almost everything in Java is an object. Understanding OOP concepts is crucial for effective Java programming.

Core Principles of OOP

There are four main principles of Object-Oriented Programming:

Encapsulation

Bundling data (attributes) and methods (functions) that operate on the data into a single unit (class), and restricting direct access to some of the object's components.

Inheritance

The ability of a class to inherit properties and methods from a parent class, enabling code reuse and establishing a relationship between classes.

Polymorphism

The ability to present the same interface for different underlying forms (data types). It allows objects of different classes to be treated as objects of a common superclass.

Abstraction

Hiding complex implementation details and showing only the necessary features of an object. It reduces complexity by hiding irrelevant details.

Classes and Objects

Classes

A class is a blueprint or template that defines the variables and methods common to all objects of a certain kind. In Java, a class is declared using the class keyword:

java
1// Class declaration
2public class Car {
3 // Instance variables (attributes)
4 private String make;
5 private String model;
6 private int year;
7 private double fuelLevel;
8
9 // Constructor
10 public Car(String make, String model, int year) {
11 this.make = make;
12 this.model = model;
13 this.year = year;
14 this.fuelLevel = 0.0;
15 }
16
17 // Methods
18 public void startEngine() {
19 System.out.println("Engine started!");
20 }
21
22 public void drive() {
23 if (fuelLevel > 0) {
24 System.out.println("The car is driving...");
25 fuelLevel -= 0.1;
26 } else {
27 System.out.println("Cannot drive. The fuel tank is empty.");
28 }
29 }
30
31 public void refuel(double amount) {
32 fuelLevel += amount;
33 System.out.println("Fuel level is now: " + fuelLevel);
34 }
35
36 // Getter methods
37 public String getMake() {
38 return make;
39 }
40
41 public String getModel() {
42 return model;
43 }
44
45 public int getYear() {
46 return year;
47 }
48
49 public double getFuelLevel() {
50 return fuelLevel;
51 }
52}

Objects

An object is an instance of a class. When a class is defined, no memory is allocated until an object is created. To create an object, you use the new keyword followed by a call to a constructor:

java
1// Creating objects from the Car class
2public class CarDemo {
3 public static void main(String[] args) {
4 // Create car objects
5 Car myCar = new Car("Toyota", "Corolla", 2022);
6 Car friendsCar = new Car("Honda", "Civic", 2021);
7
8 // Using object methods
9 myCar.refuel(5.0);
10 myCar.startEngine();
11 myCar.drive();
12
13 // Accessing object properties using getter methods
14 System.out.println("My car is a " + myCar.getYear() + " " +
15 myCar.getMake() + " " + myCar.getModel());
16
17 friendsCar.refuel(3.5);
18 System.out.println("Friend's car fuel level: " + friendsCar.getFuelLevel());
19 }
20}

Important:

Each object created from a class has its own set of instance variables. Changes to one object's instance variables don't affect other objects of the same class.

Encapsulation

Encapsulation is the technique of making the fields in a class private and providing access to them via public methods. It's a protective barrier that keeps the data and code safe from external interference and misuse.

Benefits of Encapsulation

  • Data Hiding: The implementation details are hidden from the outside world
  • Increased Flexibility: You can change the implementation without affecting the code that uses the class
  • Reusability: Encapsulated code can be reused easily
  • Testing: Encapsulated code is easier to test as the units are well-defined

Implementing Encapsulation

In Java, encapsulation is implemented by:

  1. Declaring the instance variables of a class as private
  2. Providing public setter and getter methods to modify and view the variables' values
java
1public class BankAccount {
2 // Private variables (encapsulated)
3 private String accountNumber;
4 private String accountHolder;
5 private double balance;
6
7 // Constructor
8 public BankAccount(String accountNumber, String accountHolder) {
9 this.accountNumber = accountNumber;
10 this.accountHolder = accountHolder;
11 this.balance = 0.0;
12 }
13
14 // Getter methods
15 public String getAccountNumber() {
16 return accountNumber;
17 }
18
19 public String getAccountHolder() {
20 return accountHolder;
21 }
22
23 public double getBalance() {
24 return balance;
25 }
26
27 // Setter method with validation
28 public void setAccountHolder(String accountHolder) {
29 if (accountHolder != null && !accountHolder.isEmpty()) {
30 this.accountHolder = accountHolder;
31 }
32 }
33
34 // Methods that modify private data
35 public void deposit(double amount) {
36 if (amount > 0) {
37 balance += amount;
38 System.out.println(amount + " deposited. New balance: " + balance);
39 } else {
40 System.out.println("Invalid deposit amount.");
41 }
42 }
43
44 public void withdraw(double amount) {
45 if (amount > 0 && amount <= balance) {
46 balance -= amount;
47 System.out.println(amount + " withdrawn. New balance: " + balance);
48 } else {
49 System.out.println("Invalid withdrawal amount or insufficient funds.");
50 }
51 }
52}

Inheritance

Inheritance is a mechanism by which one class (child or subclass) can inherit the properties and methods of another class (parent or superclass). It promotes code reuse and establishes a relationship between classes.

In Java, inheritance is implemented using the extends keyword:

java
1// Parent class
2public class Vehicle {
3 protected String make;
4 protected String model;
5 protected int year;
6
7 public Vehicle(String make, String model, int year) {
8 this.make = make;
9 this.model = model;
10 this.year = year;
11 }
12
13 public void startEngine() {
14 System.out.println("Engine started!");
15 }
16
17 public void stopEngine() {
18 System.out.println("Engine stopped.");
19 }
20
21 public String getInfo() {
22 return year + " " + make + " " + model;
23 }
24}
25
26// Child class inheriting from Vehicle
27public class Car extends Vehicle {
28 private int numberOfDoors;
29 private boolean isConvertible;
30
31 public Car(String make, String model, int year, int numberOfDoors, boolean isConvertible) {
32 super(make, model, year); // Call the parent constructor
33 this.numberOfDoors = numberOfDoors;
34 this.isConvertible = isConvertible;
35 }
36
37 // Override parent method
38 @Override
39 public void startEngine() {
40 System.out.println("Car engine started with key.");
41 }
42
43 // New method specific to Car
44 public void honk() {
45 System.out.println("Honk! Honk!");
46 }
47
48 // Getter methods
49 public int getNumberOfDoors() {
50 return numberOfDoors;
51 }
52
53 public boolean isConvertible() {
54 return isConvertible;
55 }
56}

Types of Inheritance

Java supports several types of inheritance:

TypeDescriptionJava Support
Single InheritanceA class inherits from one parent classSupported
Multiple InheritanceA class inherits from multiple parent classesNot supported directly (but can be achieved with interfaces)
Multilevel InheritanceA class inherits from a child class (chain of inheritance)Supported
Hierarchical InheritanceMultiple classes inherit from a single parent classSupported

Polymorphism

Polymorphism means "many forms" and it occurs when we have many classes that are related to each other by inheritance. It allows us to perform a single action in different ways.

In Java, polymorphism is mainly divided into two types:

1. Compile-time Polymorphism (Method Overloading)

Method overloading allows a class to have more than one method with the same name if their parameter lists are different:

java
1public class Calculator {
2 // Method overloading example
3
4 // Method to add two integers
5 public int add(int a, int b) {
6 return a + b;
7 }
8
9 // Method to add three integers (different number of parameters)
10 public int add(int a, int b, int c) {
11 return a + b + c;
12 }
13
14 // Method to add two doubles (different parameter types)
15 public double add(double a, double b) {
16 return a + b;
17 }
18
19 // Method to concatenate two strings (different parameter types)
20 public String add(String a, String b) {
21 return a + b;
22 }
23}

2. Runtime Polymorphism (Method Overriding)

Method overriding occurs when a subclass has the same method as the parent class. In this case, the method in the subclass overrides the method in the parent class:

java
1// Parent class
2class Animal {
3 public void makeSound() {
4 System.out.println("Animal makes a sound");
5 }
6}
7
8// Child class overriding the method
9class Dog extends Animal {
10 @Override
11 public void makeSound() {
12 System.out.println("Dog barks: Woof! Woof!");
13 }
14}
15
16// Child class overriding the method
17class Cat extends Animal {
18 @Override
19 public void makeSound() {
20 System.out.println("Cat meows: Meow!");
21 }
22}
23
24// Using polymorphism
25public class AnimalDemo {
26 public static void main(String[] args) {
27 // Create an array of Animal objects
28 Animal[] animals = new Animal[3];
29 animals[0] = new Animal();
30 animals[1] = new Dog();
31 animals[2] = new Cat();
32
33 // Call the makeSound method for each animal
34 for (Animal animal : animals) {
35 animal.makeSound(); // This will call the appropriate method based on the actual object type
36 }
37
38 // Output:
39 // Animal makes a sound
40 // Dog barks: Woof! Woof!
41 // Cat meows: Meow!
42 }
43}

Abstraction

Abstraction is the concept of hiding the complex implementation details and showing only the necessary features of an object. It helps in reducing programming complexity and effort.

In Java, abstraction can be achieved using:

1. Abstract Classes

An abstract class is a class that cannot be instantiated and may contain abstract methods (methods without a body):

java
1// Abstract class
2abstract class Shape {
3 // Abstract method (no implementation)
4 public abstract double calculateArea();
5
6 // Concrete method
7 public void display() {
8 System.out.println("This is a shape with area: " + calculateArea());
9 }
10}
11
12// Concrete subclass
13class Circle extends Shape {
14 private double radius;
15
16 public Circle(double radius) {
17 this.radius = radius;
18 }
19
20 // Implementation of abstract method
21 @Override
22 public double calculateArea() {
23 return Math.PI * radius * radius;
24 }
25}
26
27// Concrete subclass
28class Rectangle extends Shape {
29 private double length;
30 private double width;
31
32 public Rectangle(double length, double width) {
33 this.length = length;
34 this.width = width;
35 }
36
37 // Implementation of abstract method
38 @Override
39 public double calculateArea() {
40 return length * width;
41 }
42}

2. Interfaces

An interface is a completely abstract class that contains only abstract methods and constants:

java
1// Interface
2interface Drawable {
3 void draw(); // Abstract method (by default)
4
5 // Default method (Java 8+)
6 default void display() {
7 System.out.println("Displaying drawable object");
8 }
9}
10
11// Class implementing the interface
12class Circle implements Drawable {
13 private double radius;
14
15 public Circle(double radius) {
16 this.radius = radius;
17 }
18
19 // Implementation of interface method
20 @Override
21 public void draw() {
22 System.out.println("Drawing a circle with radius: " + radius);
23 }
24}
25
26// Class implementing the interface
27class Rectangle implements Drawable {
28 private double length;
29 private double width;
30
31 public Rectangle(double length, double width) {
32 this.length = length;
33 this.width = width;
34 }
35
36 // Implementation of interface method
37 @Override
38 public void draw() {
39 System.out.println("Drawing a rectangle with length: " + length + " and width: " + width);
40 }
41}

Practice Exercises

  1. Create a class hierarchy for different types of vehicles (car, motorcycle, truck) with appropriate properties and methods.
  2. Implement a banking system with different types of accounts (savings, checking) that inherit from a common base account class.
  3. Design a shape class hierarchy with methods to calculate area and perimeter for different shapes.
  4. Create a payroll system for different types of employees (full-time, part-time, contractor) with different payment calculations.
  5. Implement an e-commerce system with products, customers, and orders using object-oriented principles.

Summary

In this tutorial, you've learned:

  • The four main principles of Object-Oriented Programming: Encapsulation, Inheritance, Polymorphism, and Abstraction
  • How to create classes and objects in Java
  • How to implement encapsulation by using private fields and public methods
  • How to use inheritance to create class hierarchies
  • How to achieve polymorphism through method overloading and overriding
  • How to implement abstraction using abstract classes and interfaces

Object-Oriented Programming is a powerful paradigm that can help you create more modular, flexible, and maintainable code. As you continue your Java journey, you'll find that mastering these concepts will greatly enhance your ability to design and implement complex software systems.

In the next tutorials, we'll dive deeper into specific OOP concepts like classes and objects, inheritance, and interfaces.

Related Tutorials

Learn about decision making and loops in Java.

Learn more

Deep dive into creating and using classes and objects in Java.

Learn more

Learn how to extend classes and create class hierarchies in Java.

Learn more