Theory of Java programming and OOPS Concepts

Part 2: Object-Oriented Programming (OOPS) with Java

2.1 Introduction to Java and OOPS

Object-Oriented Programming (OOPS) is a powerful paradigm for modeling complex, real-world problems by organizing software design around data, or objects, rather than functions and logic. Java was designed from the ground up with OOPS principles at its core. Its "write once, run anywhere" philosophy, enabled by the Java Virtual Machine (JVM), underscores its significance as a platform-independent language.

  • What is OOPS? Object-Oriented Programming (OOPS) is a programming paradigm based on the concept of "objects," which can contain both data (in the form of fields, often known as attributes or properties) and code (in the form of procedures, often known as methods). The central idea is to model real-world entities as software objects.

  • Why do we use OOPS? OOPS provides several key benefits that make it suitable for developing complex, scalable, and maintainable software:

    • Modularity: Encapsulation allows objects to be self-contained, making troubleshooting and collaborative development easier.

    • Reusability: Inheritance allows new classes to reuse code from existing classes, reducing redundancy.

    • Flexibility: Polymorphism allows a single interface to be used for a general class of actions.

    • Data Security: Abstraction and encapsulation hide complex implementation details and protect data from unauthorized access.

  • What are the principles/pillars of OOPS? The four main principles, or pillars, of OOPS are:

    1. Encapsulation

    2. Inheritance

    3. Polymorphism

    4. Abstraction

  • What is Java? Java is a high-level, class-based, object-oriented programming language designed to have as few implementation dependencies as possible. It is a general-purpose language intended to let application developers "write once, run anywhere" (WORA), meaning that compiled Java code can run on all platforms that support Java without the need for recompilation.

  • Why does Java use OOPS? Java was built to be an object-oriented language from the beginning because the OOPS paradigm helps manage the complexity of modern software applications. By organizing code into objects and classes, Java promotes a clear, modular structure that is easier to maintain, reuse, and scale.

  • Why is Java platform-independent? / Is Java platform dependent or platform independent? (and why?) Java is platform-independent. This is one of its most defining features. The reason for this is its compilation and execution process, which involves the Java Virtual Machine (JVM) and bytecode.

  • What is the JVM (Java Virtual Machine)? The JVM is an abstract computing machine or a virtual machine that enables a computer to run Java programs. When you compile a Java program, the compiler translates the source code not into machine code for a specific processor, but into an intermediate format called bytecode. The JVM on any given platform (Windows, macOS, Linux) knows how to read this universal bytecode and translate it into the native machine instructions for that specific platform.

  • What is bytecode? Bytecode is the intermediate, platform-independent code generated by the Java compiler. It is a set of instructions for the JVM. Because the same bytecode can be executed by any JVM, regardless of the underlying hardware or operating system, Java achieves platform independence.

These high-level concepts are built upon a foundation of four key principles, often called the pillars of OOPS.

2.2 The Four Pillars of OOPS

The power and elegance of Object-Oriented Programming are derived from four fundamental principles: Encapsulation, Inheritance, Polymorphism, and Abstraction. A thorough understanding of each pillar is essential to writing robust, scalable, and maintainable object-oriented code that is both flexible and secure.

2.2.1 Encapsulation

Encapsulation is the practice of bundling data (attributes) and the methods that operate on that data into a single unit, or class, while restricting direct access to some of the object's components.

  • What is encapsulation? Encapsulation is the mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class are hidden from other classes and can be accessed only through the methods of their current class. This is also known as data hiding. It is primarily achieved by declaring class fields as private and providing public getter and setter methods to access and modify their values. The primary benefit is data protection and code maintainability.

2.2.2 Inheritance

Inheritance is a mechanism wherein a new class derives properties and behaviors (fields and methods) from an existing class, promoting code reuse and establishing a natural hierarchy.

  • What is inheritance? Inheritance is a fundamental pillar of OOPS in which one object acquires all the properties and behaviors of a parent object. The class that inherits the properties is known as the subclass (or child class), and the class whose properties are inherited is known as the superclass (or parent class). This creates an "is-a" relationship and is a powerful tool for code reuse.

  • What is single inheritance? Single inheritance is when a class inherits from only one superclass. This is the most basic form of inheritance. class Dog extends Animal { ... } // Dog inherits from Animal.

  • Will Java support hierarchical inheritance? Yes. Hierarchical inheritance is when multiple subclasses inherit from a single superclass. Java fully supports this. For example, Dog, Cat, and Cow classes could all inherit from a single Animal class.

  • Does Java support multiple inheritance? Java does not support multiple inheritance with classes. This means a class cannot extend more than one other class. This decision was made to avoid the "Diamond Problem," which leads to ambiguity when a class inherits methods with the same signature from two different superclasses. However, Java achieves a form of multiple inheritance through interfaces, as a class can implement multiple interfaces.

2.2.3 Polymorphism

Polymorphism, which means "many forms," allows objects of different classes to be treated as objects of a common superclass, enabling methods to perform different actions depending on the object that invokes them.

  • What is polymorphism? Polymorphism is the ability of an object to take on many forms. In programming, it means that a single action can be performed in different ways. For example, you might have a draw() method that draws a circle, a square, or a triangle depending on the specific object type.

  • What are the types of polymorphism? There are two main types of polymorphism in Java:

    1. Compile-time Polymorphism (or Static Polymorphism): This is achieved through method overloading. The decision of which method to call is made at compile time.

    2. Run-time Polymorphism (or Dynamic Polymorphism): This is achieved through method overriding. The decision of which method to call is resolved at runtime by the JVM.

  • What is the difference between method overloading and method overriding?

Feature
Method Overloading
Method Overriding

Purpose

To increase the readability of the program.

To provide a specific implementation of a method already provided by its superclass.

Location

Occurs within the same class.

Involves two classes (a superclass and a subclass).

Parameters

Must have a different number of parameters or different types of parameters.

Must have the same parameters (name, number, and type) as in the parent class.

Relationship

Not related to inheritance.

Directly related to inheritance; can only happen in a subclass.

Polymorphism

Example of compile-time polymorphism.

Example of run-time polymorphism.

  • What is the difference between compile-time polymorphism and run-time polymorphism?

Basis for Comparison
Compile-time Polymorphism
Run-time Polymorphism

Also Known As

Static Binding, Early Binding

Dynamic Binding, Late Binding

How It's Achieved

Method Overloading, Operator Overloading

Method Overriding

Binding Time

The call is bound to the method definition at compile time.

The call is bound to the method definition at runtime.

Performance

Faster, as the binding is done during compilation.

Slower, as the binding is done during runtime.

Flexibility

Less flexible, as everything is decided at compile time.

More flexible, as it allows for dynamic method invocation.

  • What is operator overloading? Operator overloading is a feature where operators like +, -, *, etc., can be given user-defined meanings for user-defined data types (classes). C++ supports operator overloading, but Java does not support operator overloading (with the exception of the + operator being overloaded for string concatenation). The designers of Java chose to omit it to simplify the language and avoid potential confusion.

2.2.4 Abstraction

Abstraction involves hiding complex implementation details and exposing only the essential features of an object, simplifying interaction and reducing the impact of changes.

  • What is abstraction? Abstraction is the process of hiding the implementation details and showing only the functionality to the user. In Java, it is achieved using abstract classes and interfaces. A good analogy is a car's accelerator pedal: you know pushing it makes the car go faster, but you don't need to know the complex mechanics of the engine and fuel injection system to use it.

  • What is an abstract class? An abstract class is a class that cannot be instantiated on its own and must be subclassed. It can contain both abstract methods (methods without a body) and concrete methods (regular methods with a body). It serves as a template for other classes.

  • What is the use of the abstract keyword/concept? The abstract keyword is used to declare a class or a method as abstract.

    • Abstract Class: If a class is declared abstract, it cannot be instantiated. Its main purpose is to be extended by other classes.

    • Abstract Method: If a method is declared abstract, it has no implementation (no body). Subclasses that are not abstract are forced to provide an implementation (override) for this method. This enforces a common contract across all subclasses.

  • What is the difference between an abstract method and a concrete method?

    • Abstract Method: An abstract method is a method declared without an implementation (no body, just a signature), followed by a semicolon. It must be declared within an abstract class. public abstract void draw();

    • Concrete Method: A concrete method is a regular method that has a complete implementation (a method body). Abstract classes can contain concrete methods, which are inherited by subclasses as-is.

With a theoretical understanding of these pillars, we can examine the practical constructs used to implement them: classes and objects.

2.3 Java Building Blocks: Classes, Objects, and Methods

Classes and objects are the primary building blocks in Java and object-oriented programming. A class can be thought of as a blueprint for creating objects, defining their properties (fields) and behaviors (methods). An object is a specific instance of a class. Constructors are special methods used to initialize new objects.

  • What are classes and objects?

    • Class: A class is a blueprint or template from which objects are created. It defines a set of properties (fields) and behaviors (methods) that are common to all objects of that type. For example, a Car class would define properties like color and speed, and methods like startEngine() and accelerate().

    • Object: An object is an instance of a class. It is a real-world entity that has state (values for its fields) and behavior (its methods). For example, myBlueToyota could be an object of the Car class with its color field set to "blue". You can create many objects from a single class.

  • What is the difference between a function and a method? In the context of Java, these terms are closely related. A method is a function that is associated with a class or an object. The term "function" is more general and is often used in procedural programming (like C), where functions can exist independently of any class. Since all executable code in Java must reside within a class, we almost exclusively use the term method.

  • What is the main method? The public static void main(String[] args) method is the entry point for any Java application. The JVM starts the execution of a Java program by invoking this specific method.

    • public: It is accessible from anywhere.

    • static: It can be called without creating an instance of the class.

    • void: It does not return any value.

    • main: This is the name of the method, fixed by convention.

    • String[] args: It accepts an array of strings as command-line arguments.

2.3.2 Constructor and Types

In Java, a constructor is a block of code similar to a method that is called when an instance(Object) of a class is created. Its primary purpose is to initialize the object and allocate memory at the time of its creation. Unlike regular methods, a constructor must have the same name as the class and has no explicit return type, not even void.

1. Default Constructor (No-Arg Constructor)

A constructor is considered a default constructor when it does not have any parameters.

  • Automatic Generation: If a programmer does not define any constructor in a class, the Java compiler automatically creates a default constructor.

  • Purpose: Its main role is to provide default values to the object’s attributes, such as 0 for integers or null for strings, depending on the data type.

2. Parameterized Constructor

A parameterized constructor is one that includes a specific number of parameters.

  • Purpose: It is used to provide different values to distinct objects at the moment they are created.

  • Flexibility: This allows a single class to produce multiple objects with unique initial states by passing specific data through the constructor's arguments.

3. Copy Constructor

The sources specify that while Java does not have a formal "copy constructor" built into the language (unlike C++), the functionality is achieved through specific implementation.

  • Implementation: It is a constructor used to copy the values of one object into another.

  • Mechanism: This is done by defining a constructor that takes an object of the same class as a parameter. It then assigns the values from the existing object's attributes to the new object's attributes.


Analogy for Understanding: Imagine you are ordering a new smartphone.

  • A Default Constructor is like buying the "standard model" that comes with the factory default wallpaper and settings.

  • A Parameterized Constructor is like "custom ordering" your phone, where you choose the specific colour and storage capacity at the time of purchase.

  • A Copy Constructor is like using a "transfer tool" to set up your new phone so that it has the exact same settings and data as your old one.

2.3.3 Difference between constructor and method

Feature
Constructor
Method

Purpose

To initialize an object.

To expose the behavior of an object.

Name

Must have the same name as the class.

Can have any name (except keywords).

Return Type

Has no return type, not even void.

Must have a return type (or void).

Invocation

Called implicitly when an object is created using the new keyword.

Called explicitly by name on an object.

To properly define these building blocks, Java provides keywords and modifiers that control their behavior and visibility.

2.4 Key Java Keywords and Modifiers

Java uses a specific set of keywords and access modifiers to control the behavior, scope, and accessibility of classes, methods, and variables. These tools are crucial for implementing OOPS principles like encapsulation by defining clear boundaries, as well as for creating class-level members (static) and defining unchangeable constants (final).

  • What are access specifiers/modifiers? Access modifiers in Java set the visibility (access level) for classes, fields, methods, and constructors. They are a key part of implementing encapsulation. There are four levels of access:

    1. public: Accessible from any other class.

    2. protected: Accessible within the same package and by subclasses in other packages.

    3. default (no keyword): Accessible only within the same package.

    4. private: Accessible only within the same class.

  • Explain public and private.

    • public: When a member (field or method) is declared public, it can be accessed from any other class in any package. This provides the widest possible level of visibility.

    • private: When a member is declared private, it can only be accessed from within the same class where it is declared. This is the most restrictive access level and is fundamental to data hiding in encapsulation.

  • What is the protected scope? The protected access modifier provides an intermediate level of access. A protected member is accessible to classes in the same package (like default access) and also to subclasses of its class, even if those subclasses are in different packages.

  • What is the static keyword? The static keyword is used to create variables and methods that belong to the class itself, rather than to an instance of the class.

    • Static Variable (Class Variable): There is only one copy of a static variable, shared among all instances of the class.

    • Static Method (Class Method): A static method can be called directly on the class without creating an object. It can only access static variables and call other static methods of the class.

  • What is the final keyword? The final keyword is used to apply restrictions on a class, method, or variable.

    • Final Variable: A final variable is a constant. Its value cannot be changed once it has been initialized.

    • Final Method: A final method cannot be overridden by any subclass.

    • Final Class: A final class cannot be extended (inherited from).

  • What is the this keyword? The this keyword is a reference variable that refers to the current object. It is mainly used to:

    1. Distinguish between instance variables and local parameters when they have the same name.

    2. Invoke a constructor of the same class from another constructor (constructor chaining).

    3. Pass the current object as an argument to another method.

  • What is the super keyword? The super keyword is a reference variable that is used to refer to the immediate parent class object. It is used to:

    1. Call the superclass's constructor from a subclass's constructor.

    2. Access a superclass's method when the subclass has overridden it.

    3. Access a superclass's field (if it's not private).

Beyond these core components, building robust applications requires handling more advanced scenarios, such as defining contracts with interfaces and managing runtime errors.

2.5 Advanced Concepts: Interfaces, Packages, and Exception Handling

Interfaces, packages, and exception handling are essential concepts for building large-scale, resilient Java applications. Interfaces provide a mechanism to achieve true abstraction and define contracts for classes. Packages help organize and group related classes and interfaces. Exception handling provides a robust mechanism for managing runtime errors gracefully, preventing program crashes.

  • What is an interface? An interface in Java is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. It represents a "contract" that a class can promise to fulfill. An interface cannot be instantiated on its own; it must be implemented by a class. It is a key mechanism for achieving 100% abstraction.

  • What is the difference between an interface and a class?

Feature
Interface
Class (including Abstract Class)

Instantiation

Cannot be instantiated.

A concrete class can be instantiated. An abstract class cannot.

Methods

By default, methods are public abstract (unless default or static).

Can contain abstract and concrete methods.

Variables

Can only have public static final variables (constants).

Can have any type of variables (static, final, non-static, etc.).

Constructors

Cannot have constructors.

Can have constructors.

Multiple Inheritance

A class can implement multiple interfaces.

A class can extend only one class.

  • What is the implements keyword? The implements keyword is used by a class to indicate that it is adhering to the contract defined by an interface. A class that implements an interface must provide a concrete implementation for all the abstract methods declared in that interface.

  • What is the difference between extends and implements?

    • extends: This keyword is used for inheritance between classes. A subclass extends a superclass, inheriting its fields and methods.

    • implements: This keyword is used for a class to conform to an interface. A class implements an interface, providing bodies for its abstract methods.

Relationship
Keyword Used
Example

Class to Class

extends

class Dog extends Animal {}

Class to Interface

implements

class MyCar implements Vehicle {}

Interface to Interface

extends

interface AdvancedVehicle extends Vehicle {}

  • What are packages? A package in Java is a namespace that organizes a set of related classes and interfaces. Conceptually, you can think of packages as being similar to folders on a computer. Using packages helps to avoid naming conflicts, control access, and make it easier to locate and use related code.

  • What is an exception? An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. It is an object that is "thrown" at runtime when an error occurs. Examples include dividing by zero, trying to access a file that doesn't exist, or accessing an array out of its bounds.

  • What is exception handling? Exception handling is a mechanism to handle runtime errors in a controlled and predictable manner, so that the normal flow of the application can be maintained. It prevents the program from crashing abruptly and allows the programmer to provide user-friendly error messages or take recovery actions.

  • What are try and catch? How do you handle an exception? The try and catch blocks are the core components of Java's exception handling mechanism.

    1. try block: You place the code that might throw an exception inside a try block.

    2. catch block: If an exception occurs in the try block, the JVM looks for a corresponding catch block that can handle that specific type of exception. The catch block contains the code that is executed to handle the error.

Last updated

Was this helpful?