Post

08. Java OOPS

🚀 Dive into the heart of Java with a complete guide to Object-Oriented Programming (OOP)! Uncover core concepts, from classes and objects to the four pillars of OOP, and understand why Java isn't purely object-oriented. 💻

08. Java OOPS

What we will learn in this post?

  • 👉 OOPS Concept in Java
  • 👉 Why Java is not a purely Object-Oriented Language?
  • 👉 Classes and Objects in Java
  • 👉 Naming Conventions in Java
  • 👉 Methods in Java
  • 👉 Access Modifiers in Java
  • 👉 Constructors in Java
  • 👉 Four Pillars of OOP in Java
  • 👉 StringJoiner in Java
  • 👉 Conclusion!

🌟 Diving into OOP in Java: A Beginner’s Guide 🌟

Let’s explore the foundational concepts of Object-Oriented Programming (OOP) in Java, which makes code more organized and reusable. We’ll cover encapsulation, inheritance, and polymorphism with easy-to-understand examples. These are key concepts when you are learning ‘Object-Oriented Programming concepts’!

📦 Encapsulation: Bundling Data and Methods

Encapsulation is like putting related data and the functions that operate on that data inside a box (an object). It hides the internal workings of an object and exposes only what’s necessary. This protects data from accidental modification. For example, a BankAccount class would encapsulate the balance and methods like deposit() and withdraw().

1
2
3
4
5
6
7
8
9
10
11
class BankAccount {
    private double balance; // Data hidden

    public void deposit(double amount) {
        balance += amount;
    }

    public double getBalance() { // Controlled access
        return balance;
    }
}
  • Key Benefit: Data security and controlled access.
  • Analogy: Like a capsule holding medicine, protecting its contents.

👪 Inheritance: Building on Existing Classes

Inheritance in Java inheritance and polymorphism allows you to create new classes (subclasses) based on existing ones (superclasses), inheriting their properties and methods. This promotes code reuse. For instance, a Dog class and Cat class can both inherit from an Animal class and have their own unique behaviors while having common attributes.

1
2
3
4
5
6
7
8
9
10
11
12
class Animal {
    String name;
    void eat() { System.out.println("Animal is eating"); }
}

class Dog extends Animal {
   void bark() { System.out.println("Woof!");}
}

class Cat extends Animal {
  void meow() { System.out.println("Meow!"); }
}
  • Key Benefit: Code reusability and establishing relationships between classes.
  • Analogy: A child inheriting traits from their parents.
  • More about inheritance: GeeksForGeeks

🎭 Polymorphism: Many Forms

Polymorphism, another core concept in Java inheritance and polymorphism, allows objects of different classes to respond to the same method call in different ways. This means, a single action can be performed in multiple ways. There are two main ways: method overriding (runtime polymorphism) and method overloading (compile-time polymorphism). For example the Animal class can have a makeSound() method, and each subclass can override it to produce the correct sound.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Animal {
  void makeSound() {System.out.println("Generic animal sound");}
}

class Dog extends Animal {
  @Override
  void makeSound() {System.out.println("Woof!");}
}

class Cat extends Animal {
  @Override
  void makeSound() {System.out.println("Meow!");}
}

//Example usage
Animal myAnimal = new Dog();
myAnimal.makeSound(); // Output will be "Woof!" because of overriding
  • Key Benefit: Flexibility and code extensibility.
  • Analogy: Like a single button press having different effects in various contexts.

Summary of OOP in Java

  • Encapsulation: Data hiding and security.
  • Inheritance: Code reuse and class hierarchies.
  • Polymorphism: Flexibility and ability to handle different objects uniformly.
  • Resource for more details: Oracle Docs These principles together make OOP in Java a very powerful paradigm for software development.

Why Java Isn’t Purely Object-Oriented 🧐

Java, while widely known for its object-oriented features, isn’t considered a purely object-oriented language. This primarily stems from its reliance on Java primitive types, which are not objects. This creates a dichotomy, hindering complete object orientation. Here’s why:

The Role of Java Primitive Types

  • What are they? Java uses primitive types like int, char, boolean, float, double, long, short, and byte to represent basic data values directly. These are not objects; they don’t have methods or belong to a class hierarchy.

    1
    2
    3
    
    int age = 30;
    double price = 19.99;
    boolean isAdult = true;
    

    In these examples, age, price, and isAdult are variables holding primitive values, not objects.

  • Why it matters: In a pure object-oriented language, everything should be an object. The lack of object nature in primitive types represents a key Java object-oriented limitations. They prevent you from directly calling methods on these values. For example you cannot directly write age.toString(). Instead, you need to wrap them in wrapper classes such as Integer, Double, or Boolean to use them as objects.
  • Wrapper classes: While Java provides wrapper classes (e.g., Integer for int, Double for double) to treat primitives as objects, the existence of the primitives themselves signals a deviation from pure object orientation. These need to be created like:

    1
    2
    
     Integer ageObject = Integer.valueOf(30);
     String ageString = ageObject.toString();
    

Contrast with Pure Object Orientation

  • In a truly object-oriented language, even numbers and booleans would be objects, allowing operations to be performed through methods associated with the object itself.
  • This lack of uniformity in Java breaks the consistency expected from a pure object-oriented language. It is a practical design decision taken to improve performance. Java’s approach is considered a hybrid, aiming to balance object-oriented principles with efficiency.

Summary of Limitations

Here’s a quick overview:

  • Java uses primitive data types which are not objects.
  • This introduces inconsistency in design as not everything is an object.
  • Although wrapper classes exist to treat primitives as objects, Java still is not purely object oriented.

Visual Representation

flowchart TD
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-dasharray:5 5
    style C fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style E fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-dasharray:5 5
    style F fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style G fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style H fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px

    A([Start 🚀]) --> B{Is it an object? 🤔}
    B -- Yes --> C[Perform operations using method calls ⚙️]
    B -- No --> D[Primitive Type, no direct method calls 🔢]
    D --> E{Needs to be wrapped? 🤔}
    E -- Yes --> F[Use Wrapper Classes like Integer, Double 🧩]
    E -- No --> G[Use the value directly ✅]
    C --> H([End 🎉])
    F --> H
    G --> H

Further Resources

🚀 Classes and Objects in Java: A Friendly Guide

Hey there! Let’s explore the fundamental concepts of classes and objects in Java, cornerstones of Java OOP (Object-Oriented Programming). Understanding these is crucial to writing efficient and well-organized code.

🧩 What are Classes in Java?

  • Think of a class as a blueprint or a template. It defines the structure and behavior of objects.
  • It specifies what data (attributes/fields) an object will hold and what actions (methods) it can perform.
  • In Java, classes are declared using the class keyword, followed by the class name.

✍️ Example of a Class

1
2
3
4
5
6
7
8
9
class Dog {
    String name;  // Attribute
    String breed; // Attribute

    // Method
    void bark() {
        System.out.println("Woof!");
    }
}

Here, Dog is a class in Java, defining that every dog object will have a name, breed, and the ability to bark.

📦 What are Objects in Java?

  • An object is a concrete instance of a class. It’s the actual entity you work with in your program.
  • You create objects in Java using the new keyword, which allocates memory for the object and calls the class’s constructor.
  • Each object has its own distinct set of values for the attributes defined in its class.

🛠️ Example of Creating and Using Objects

1
2
3
4
5
6
7
8
9
10
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog(); // Creates an object of the Dog class
        myDog.name = "Buddy";   // Setting attribute values
        myDog.breed = "Golden Retriever";
        System.out.println(myDog.name);  // Output: Buddy
        myDog.bark(); // Calls the bark method
    }
}



  • In this example, myDog is an object of the Dog class. We assign values to its attributes (name, breed) and invoke its bark() method.

    🤝 How Classes and Objects Interact

  • Classes define the type of an object, and objects are instances of that type.
  • A single class can create many different objects, each with its own unique data.
  • Objects interact by calling each other’s methods, forming a collaborative network of operations in your program. This is a fundamental aspect of Java OOP.
graph LR
    %% Node Styles
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style C fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#FF9800,stroke:#F57C00,color:#000000,font-size:12px,stroke-width:2px
    style E fill:#FF9800,stroke:#F57C00,color:#000000,font-size:12px,stroke-width:2px

    %% Graph Structure
    A[Class **Dog 🐕**]
    B[Object 1: **myDog 🐾**]:::objectNode
    C[Object 2: **yourDog 🐾**]:::objectNode

    %% Attribute and Method Labels
    D["Attributes 🏷️<br>- name: String<br>- breed: String"]
    E["Methods 🗣️<br>- bark(): void"]

    %% Connections
    A --> D
    A --> E
    A --> B
    A --> C
    B --- D
    B --- E
    C --- D
    C --- E

    %% Styling Classes
    classDef objectNode fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px


Key Takeaways:

  • Classes are blueprints, while objects are real-world entities.
  • Objects are instances of classes.
  • Java OOP relies heavily on this interaction to structure programs effectively.
  • Classes define the type of data and functionality an object can have.

Resources for More Info:

By understanding how classes and objects work together, you can leverage the full power of Java’s object-oriented approach. Happy coding! 🎉

🚀 Java Naming Conventions: Making Code Readable

Why Java Naming Matters 🧐

Following good Java naming conventions is vital for achieving excellent Java code readability. Consistent and clear naming practices make your code easier to understand, maintain, and collaborate on. It’s a core part of Java best practices that greatly reduces confusion and bugs. Think of it like writing clear, understandable sentences - we don’t just throw words around randomly!

Key Naming Rules in Java 🚦

Here’s a breakdown of the key rules:

  • Classes:

    • Use PascalCase (also known as UpperCamelCase).
    • Nouns or noun phrases representing a thing (e.g., BankAccount, CustomerDetails).
    • Avoid abbreviations.
    1
    2
    3
    4
    5
    
    // Good:
    class UserProfile {}
    
    // Bad:
    class UserProf {}
    
  • Methods:

    • Use camelCase.
    • Verbs or verb phrases representing actions (e.g., calculateSalary(), getUserName()).
    1
    2
    3
    4
    5
    
    // Good:
    public void printMessage() {}
    
    // Bad:
    public void Printmessage() {}
    
  • Variables:

    • Use camelCase.
    • Use descriptive names (e.g., firstName, totalAmount).
    • Avoid single-letter names (except for loop counters, such as i, j).
    1
    2
    3
    4
    5
    
    // Good:
    int userAge;
    
    // Bad:
    int a;
    
  • Constants:

    • Use UPPER_SNAKE_CASE.
    • Make them static and final (e.g., MAX_SIZE, DEFAULT_COLOR).
    1
    2
    3
    4
    5
    
    // Good:
    public static final int MAX_LENGTH = 100;
    
    // Bad:
    public final int max_Length = 100;
    

Examples 📝

Class Example

1
2
3
4
// Good:
public class StudentRegistration {
    // ...
}

Method Example

1
2
3
4
5
// Good:
public String getStudentName() {
    // ...
}

Variable Example

1
2
3
// Good:
int studentId;

Constant Example

1
2
// Good:
public static final double PI = 3.14159;

Why These Practices? 💡

  • Clarity: Naming conventions create consistency which makes the code more clear and easier to read.
  • Maintainability: Properly named elements makes it easier to understand the purpose and function of code, hence maintenance is easier.
  • Collaboration: Everyone can quickly understand the code, which simplifies teamwork.

More Resources 📚

By adhering to these simple but crucial Java naming conventions, you’ll significantly improve the overall Java code readability of your projects and make them more maintainable, ultimately leading to better software.

🚀 Understanding Methods in Java 🚀

Methods in Java are like mini-programs within a bigger program. They’re blocks of code that perform specific tasks. Think of them as actions your objects can take. They’re fundamental for organizing and reusing code, crucial aspects of encapsulation. Instead of writing the same logic repeatedly, you can define a method and call it whenever needed. This makes your code cleaner, easier to understand, and less prone to errors. Let’s explore how to define and use methods in Java.

Defining a Method (Java Function Definition) 🛠️

A Java method definition typically includes:

  • Access Modifier: Determines the method’s visibility (e.g., public, private, protected).
  • Return Type: Specifies the type of data the method will return (e.g., int, String, void if it doesn’t return anything).
  • Method Name: The identifier used to call the method.
  • Parameters (Optional): Values passed into the method enclosed in parentheses, e.g., (int x, String y).
  • Method Body: Code block enclosed in curly braces {} that contains the instructions the method executes.
1
2
3
4
    public int add(int a, int b) { // Example method definition
        int sum = a + b;
        return sum;
    }

Invoking a Method (Java Method Examples) 📞

To use a method, you need to “call” or invoke it. This involves using the method name followed by parentheses, and any necessary arguments if required.

1
2
3
4
5
6
7
8
9
10
11
12
13
    public class Main {
        public static void main(String[] args) {
          Calculator calc = new Calculator();
          int result = calc.add(5, 3);  // Example method invocation
          System.out.println("The sum is: " + result); // Output: The sum is: 8
        }
    }
    class Calculator{
         public int add(int a, int b) { // Example method definition
            int sum = a + b;
            return sum;
        }
    }

Significance of Methods

  • Code Reusability: Write once, use many times.
  • Modularity: Breaks complex tasks into smaller manageable parts.
  • Organization: Improves code readability and maintainability.
  • Abstraction: Hides complex implementations from the user, focusing on functionality.

Here’s a simple flowchart for understanding method invocation:

flowchart TD
    %% Node Styles
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-dasharray:5,5
    style C fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-dasharray:5,5
    style E fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style F fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style G fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px

    %% Flowchart Structure
    A[Start 🟢] --> B{Method Call 🟠}
    B --> C[Execute Method Code 🔧]
    C --> D{Return Value? 🟠}
    D -- Yes --> E[Process Return Value 🔄]
    D -- No --> F[Continue Program ⏩]
    E --> F
    F --> G[End 🟢]

For a deeper dive into methods, you might find these resources helpful:

🔐 Understanding Java Access Modifiers: A Friendly Guide

Let’s dive into the world of Java access modifiers and how they play a vital role in Java encapsulation. These modifiers control the visibility and accessibility of class members (variables, methods, constructors). Think of them as gatekeepers for your code, managing who can see and use what. We’ll explore the four types: public, private, protected, and default (no keyword).

🔍 Public Access Modifier

  • The public modifier makes a member accessible from anywhere. This is the least restrictive access level.
  • It’s like opening the door wide! 🚪
1
2
3
4
5
6
7
public class PublicExample {
    public String message = "Hello from Public!";

    public void greet() {
        System.out.println(message);
    }
}
  • Code example: The message variable and greet method in PublicExample can be accessed from any other class.

🔒 Private Access Modifier

  • The private modifier is the most restrictive. Members declared as private are only accessible within the class they are defined in.
  • It’s like keeping a secret! 🤫
1
2
3
4
5
6
7
8
9
10
11
class PrivateExample {
    private int secretCode = 1234;

    private void showSecret() {
        System.out.println("The secret code is: " + secretCode);
    }

    public void revealSecret() { // Public method to access the private secretCode
        showSecret();
    }
}
  • Code example: secretCode and showSecret in PrivateExample cannot be directly accessed from outside. We use revealSecret() (a public method) as a gateway. This upholds Java encapsulation by hiding internal details and providing controlled access.

🛡️ Protected Access Modifier

  • The protected modifier allows access within the same package, as well as access by subclasses (even in a different package).
  • Think of it as being accessible within the family and trusted friends. 👨‍👩‍👧‍👦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package package1;

public class ProtectedExample {
    protected String name = "Protected Name";
}

package package2;
import package1.ProtectedExample;

class SubProtected extends ProtectedExample {
    public void printName(){
    System.out.println(this.name);
}
}
  • Code example: name is accessible within package1 and also by subclass SubProtected in package2.

📦 Default (Package-Private) Access Modifier

  • When no modifier is specified, it’s considered default access. Default access allows access within the same package only.
  • It’s like neighborhood access! 🏘️
1
2
3
4
5
6
7
8
package mypackage;

class DefaultExample {
    String message = "Hello from default!";
    void showMessage(){
        System.out.println(message);
    }
}
  • Code example: message and showMessage are only accessible by other classes in the mypackage.

💡 Key Takeaways & Impact on Encapsulation

  • Java access modifiers help you implement Java encapsulation effectively. They enable you to bundle data with methods and hide the internal implementation details from the outside world.
  • public: Widest access.
  • private: Most restricted access, used for data hiding.
  • protected: Allows inheritance-based access and is open within the same package.
  • Default: Package-level access.
Access ModifierDescriptionVisibility
publicAllows the widest access to the members of a class or interface. No restrictions on access.Accessible from anywhere
privateProvides the most restricted access, primarily used to hide internal details and protect data. Only accessible within the same class.Accessible only within the same class
protectedAllows access within the same package and in subclasses (even if they are in a different package).Accessible within package and subclasses
DefaultWhen no modifier is specified, it allows package-level access. Members are accessible within the same package only.Accessible within the same package
flowchart TD
    %% Node Styles
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style C fill:#FF9800,stroke:#F57C00,color:#FFFFFF,font-size:16px,stroke-width:2px
    style E fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:16px,stroke-width:2px
    style H fill:#9C27B0,stroke:#7B1FA2,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#81C784,stroke:#388E3C,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#FFB74D,stroke:#F57C00,color:#FFFFFF,font-size:14px,stroke-width:2px
    style F fill:#64B5F6,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style G fill:#64B5F6,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style I fill:#CE93D8,stroke:#7B1FA2,color:#FFFFFF,font-size:14px,stroke-width:2px

    %% Flowchart Structure
    A[Public 🌐] --> B(Anywhere 🌍)
    C[Private 🔒] --> D(Within Class 🏠)
    E[Protected 🔑] --> F(Same Package 📦)
    E --> G(Subclasses 🧬)
    H[Default 📦] --> I(Same Package 📦)

Using these modifiers allows you to control the level of interaction with your classes, improving code maintainability and reducing accidental bugs. By making internal data private, for example, you prevent external code from directly manipulating it, thus preventing unforeseen errors.

📚 Resources

I hope this was helpful in understanding Java access modifiers and Java encapsulation! Happy coding! 🎉

🛠️ Understanding Java Constructors 🚀

Let’s dive into the world of Java constructors! They’re special methods that play a crucial role in creating and setting up new objects. Think of them as the object’s “birth certificate,” making sure everything’s in place from the get-go.

The Role of Java Constructors

  • Object Initialization: When you create a new object in Java, you need a way to set its initial state – its starting values for variables. That’s where constructors come in! They’re automatically called when you use the new keyword to make a new instance of a class.

  • Setting up Instance Variables: Constructors ensure that your object’s instance variables are given meaningful starting values, instead of the default ones Java gives if we don’t initialize them ourselves.

Default vs. Parameterized Constructors

We have two types of constructors:

Default Constructor in Java

  • This is a special constructor that Java creates automatically if you don’t define any constructors in your class.
  • It takes no arguments (no parameters) and performs a basic initialization – typically setting instance variables to their default values (e.g., 0 for int, null for objects).
1
2
3
4
5
6
7
8
9
10
11
12
//Example of class with default constructor
class Dog {
    String breed; // Instance variable, will be 'null' initially
}

public class Main {
  public static void main(String[] args) {
    Dog myDog = new Dog(); // Default constructor is called implicitly
    System.out.println("Breed of dog is "+myDog.breed); // Output: null
  }
}

Parameterized Constructor Java

  • These are constructors that you define, which take one or more arguments (parameters).
  • They allow you to set the object’s instance variables to specific values when you create the object.
  • This gives you flexibility and allows you to tailor the object’s initial state precisely to your needs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Example of a class with parameterized constructor
class Cat {
    String name;
    int age;
    // Parameterized constructor
    public Cat(String catName, int catAge) {
        name = catName;
        age = catAge;
    }
}

public class Main {
  public static void main(String[] args) {
     Cat myCat = new Cat("Whiskers", 3); // Parameterized constructor call
    System.out.println("Name: " + myCat.name + ", Age: " + myCat.age); // Output: Name: Whiskers, Age: 3
  }
}

Constructor Flow

flowchart TD
    %% Node Styles
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-width:2px,stroke-dasharray:5,5
    style C fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#64B5F6,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style E fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style F fill:#FFC107,stroke:#FFA000,color:#000000,font-size:14px,stroke-width:2px
    style G fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px

    %% Flowchart Structure
    A[Start Object Creation 🛠️] --> B{Does constructor exist? 🤔}
    B -- Yes --> C[Call Constructor 🔧]
    C --> D[Initialize Instance Variables 🗂️]
    D --> E[Object Created 🎉]
    B -- No --> F[Call Default Constructor ⚙️]
    F --> D
    E --> G[End 🚀]


Key Takeaways

  • No Return Type: Constructors don’t have a return type, not even void.
  • Same Name: They have the same name as the class itself.
  • Overloading: You can have multiple constructors with different parameter lists (constructor overloading).

For more in-depth information, you can check out these resources:

By understanding Java constructors, you gain better control over object creation, making your programs more robust and easier to maintain!

The Four Pillars of OOP in Java 🚀

Understanding the four pillars of OOP is crucial for writing effective code. Let’s explore how encapsulation inheritance polymorphism abstraction in Java are implemented. These are the cornerstones of Java OOP implementation, making code reusable, maintainable, and scalable.

Encapsulation 📦

  • What it is: Bundling data (attributes) and methods that operate on the data within a class. It also restricts direct access to some components, protecting data integrity. We use access modifiers like private, public, and protected in Java.

  • Example:

    1
    2
    3
    4
    5
    
    class BankAccount {
        private double balance; // Encapsulated data
        public double getBalance() { return balance; } // Getter
        public void deposit(double amount) { balance += amount; } // Setter
    }
    
  • Here, balance is private, preventing direct modification, while methods allow controlled interaction.

Inheritance 👪

  • What it is: A mechanism where a class inherits properties and methods from another class (parent class). It promotes code reusability. In Java, we use the extends keyword.

  • Example:

    1
    2
    3
    4
    5
    6
    7
    
    class Animal {
        void eat() { System.out.println("Animal is eating"); }
    }
    
    class Dog extends Animal {
        void bark() { System.out.println("Woof!");}
    }
    
  • Dog inherits eat() from Animal and has its own bark() method.

  • Mermaid Diagram:

        classDiagram
            %% Node Styles
            class Animal {
                + eat() 🥩
            }
            class Dog {
                + bark() 🐾
            }
            Dog --|> Animal : Inherits 🧬
    
    

Polymorphism 🎭

  • What it is: The ability of an object to take on many forms. In Java, achieved through method overriding and method overloading.

  • Example:

    1
    2
    3
    4
    5
    6
    7
    
    class Shape {
      void draw() {System.out.println("Drawing a shape");}
    }
    class Circle extends Shape{
      @Override
        void draw() {System.out.println("Drawing a circle");}
    }
    
  • The draw() method is polymorphic since Shape class’ draw() method is overriden in Circle.

  • Further Reading : Polymorphism in Java

Abstraction 💡

  • What it is: Showing only essential information and hiding complex details. Abstract classes and interfaces achieve this in Java.

  • Example:

    1
    2
    3
    4
    5
    6
    7
    8
    
    abstract class Shape {
      abstract void draw();
    }
    
    class Rectangle extends Shape{
        @Override
        void draw(){ System.out.println("Drawing Rectangle"); }
    }
    
  • Shape is abstract, and concrete classes like Rectangle must provide their implementation of draw(). It provides a generalized view while hiding underlying complexities.

  • Further Reading : Abstract Class and Abstract Methods

By mastering these four pillars of OOP, you’ll write more flexible and robust Java programs. These principles are fundamental to successful Java OOP implementation.

The Mighty StringJoiner in Java: Joining Strings Made Easy 🚀

Let’s explore the StringJoiner class in Java, a handy tool for efficiently joining strings in Java. It simplifies the process of combining strings with a specified delimiter, prefix, and suffix. Forget clunky concatenation, StringJoiner brings structure and readability to your string-building tasks.

Why Use StringJoiner? 🤔

  • Clarity: Makes your code cleaner and easier to understand compared to using + repeatedly.
  • Efficiency: StringJoiner is more efficient for joining multiple strings than using the + operator in loops, as + creates new String objects in each iteration.
  • Customizable: Allows adding prefixes, suffixes, and specific delimiters.
  • Less Error-Prone: Reduces the risk of missing a delimiter or adding an extra space in the process of string concatenation.

How to Use StringJoiner 🛠️

Here’s how it works, using our previous example and adding some new tricks:

Basic String Joining

1
2
3
4
5
6
7
8
9
import java.util.StringJoiner;

public class StringJoinerExample {
    public static void main(String[] args) {
        StringJoiner joiner = new StringJoiner(", ");
        joiner.add("Apple").add("Banana").add("Cherry");
        System.out.println(joiner.toString()); // Output: Apple, Banana, Cherry
    }
}

Adding Prefix and Suffix

1
2
3
4
5
6
7
8
9
import java.util.StringJoiner;

public class StringJoinerExample {
    public static void main(String[] args) {
        StringJoiner joinerWithPrefixSuffix = new StringJoiner(", ", "[", "]");
        joinerWithPrefixSuffix.add("Red").add("Green").add("Blue");
        System.out.println(joinerWithPrefixSuffix.toString()); // Output: [Red, Green, Blue]
    }
}

Joining Numbers

1
2
3
4
5
6
7
8
9
10
11
import java.util.StringJoiner;

public class StringJoinerExample {
    public static void main(String[] args) {
        StringJoiner numberJoiner = new StringJoiner("-", "(", ")");
        for(int i = 1; i<=5; i++){
          numberJoiner.add(String.valueOf(i));
        }
        System.out.println(numberJoiner.toString()); // Output: (1-2-3-4-5)
    }
}
  • We create a StringJoiner instance by passing the delimiter to the constructor.
  • We add the strings we want to combine by using the .add() method.
  • The toString() method returns the joined string.
  • You can also add a prefix and suffix using the StringJoiner’s constructor with the respective parameters.

Advantages Summary 🌟

  • Simplicity: Provides an easy-to-use API for joining strings in Java.
  • Flexibility: Allows custom delimiters, prefixes, and suffixes.
  • Performance: More efficient than using the + operator repeatedly for string concatenation.
  • Readability: Makes code cleaner and easier to maintain.

Diagram

graph LR
    %% Node Styles
    style A fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px
    style B fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style C fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style D fill:#FF9800,stroke:#F57C00,color:#000000,font-size:16px,stroke-dasharray: 5 5,stroke-width:2px
    style E fill:#2196F3,stroke:#1976D2,color:#FFFFFF,font-size:14px,stroke-width:2px
    style F fill:#4CAF50,stroke:#2E7D32,color:#FFFFFF,font-size:16px,stroke-width:2px

    %% Flowchart Structure
    A([Start 🔗]) --> B{Create StringJoiner with delimiter 🧩}
    B --> C{Add string to joiner ➕}
    C --> D{More strings? 🔄}
    D -- Yes ✔️ --> C
    D -- No ❌ --> E{Get joined string 🖇️}
    E --> F([End 🚀])

Resources:

Let’s start using StringJoiner and see how it transforms your string-joining experience! 🎉

Conclusion

Well, that’s a wrap! 🎉 I hope you enjoyed reading this and found it helpful! Now it’s your turn. What are your thoughts? 🤔 Do you have any tips or ideas to share? I’d love to hear from you! Please drop your comments, feedback, or suggestions down below. 👇 Let’s chat and learn together! 😊 Your input is super appreciated! 🙏

This post is licensed under CC BY 4.0 by the author.