Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Fundamentals: Object-Oriented Programming Principles

Tech May 18 3

Object-Oriented Programming

Core Principles of OOP

  1. Inheritance: The mechanism where a new class derives properties and behaviors from an existing class. The existing class is referred to as the superclass or base class, while the new class is called the subclass or derived class. Inheritance ensures continuity in evolving software systems and serves as a crucial technique for encapsulating variable factors within a program.
  2. Encapsulation: The bundling of data with the methods that operate on that data, restricting direct access to an object's components. The essence of object-oriented programming is modeling the real world as a collection of self-contained, independent objects. Methods within a class encapsulate implementation details, and a class itself encapsulates data and its associated operations. Encapsulation effectively conceals all implementation details, exposing only minimal programming interfaces to the outside world.
  3. Polymorphism: The ability of different object types to respond to the same message in different ways. With polymorphism, the same object reference can invoke the same method but execute different behaviors. Polymorphism is categorized into compile-time polymorphism and runtime polymorphism. If we view object methods as services provided to external systems, runtime polymorphism can be understood as: when System A accesses services provided by System B, System B may offer multiple implementation approaches, all transparent to System A. Method overloading implements compile-time polymorphism (also known as early binding), while method overriding implements runtime polymorphism (also known as late binding). Runtime polymorphism represents the most sophisticated aspect of object-oriented programming. Achieving polymorphism requires two steps: ① Method overriding (subclasses inherit and override methods from their parent class); ② Object type casting (using a parent type reference to point to a child type object, causing the same reference to exhibit different behaviors when calling the same method based on the specific child object).
  4. Abstraction: The process of identifying common characteristics among a group of objects to construct a class, encompassing both data abstraction and behavior abstraction. Abstraction focuses on what attributes and behaviors an object has without concerning itself with the implementation details of these behaviors.

Important: The String class in Java is marked as final, which means it cannot be extended.

Q: What mechanism enables polymorphism in Java?

A: Polymorphism in Java is achieved through parent class or interface reference variables that can point to instances of child classes or concrete implementations. The methods invoked are dynamically bound at runtime to the actual method of the object instance being referenced, rather than to the method defined in the reference variable's type.

Access Modifiers

The following table illustrates the accessibility scope of different modifiers (absence indicates default access):

Modifier Same Class Same Package Subclass Other Package
public
protected
default
private

Object Cloning

In programming scenarios, you may encounter situations where you have an object A that contains valid values, and you need to create a completely new object B with the same initial values, where any subsequent modifications to B won't affect A. This means A and B are independent objects, with B's initial values derived from A. In Java, simple assignment statements cannot fulfill this requirement. While several approaches can achieve this, implementing the clone() method is both the simplest and most efficient solution.

Comparison: new vs clone()

  • The new operator primarily allocates memory. When the program executes new, it first examines the type following the operator (to determine the required memory size). After memory allocation, the constructor is called to initialize the object's fields. This initialization step is called object initialization. After the constructor returns, the object is fully created, and its reference (memory address) can be exposed for external use.
  • The clone() method similarly begins with memory allocation, but it allocates memory identical to that of the original object (the one invoking the method). It then fills the new object's fields using corresponding values from the original object. After this process completes, the method returns, creating a new identical object whose reference can also be exposed externally.

Reference Copying vs Object Copying

The following code demonstrates reference copying, where both variables point to the same object:

Employee emp = new Employee(30, "Johnson");
Employee empCopy = emp;
System.out.println(emp);
System.out.println(empCopy);

The output memory addresses will be identical, confirming that emp and empCopy merely reference the same object.

In contrast, the following code performs true object cloning, creating a distinct copy:

Employee emp = new Employee(30, "Johnson");
Employee empClone = (Employee) emp.clone();
System.out.println(emp);
System.out.println(empClone);

This code produces different memory addresses, confirming that a new object was created rather than copying the reference.

Deep Copy vs Shallow Copy

Consider a class with multiple fields, including primitive types and reference types. To implement cloning, the class must implement the Cloneable interface and override the clone() method. For example:

public class Employee implements Cloneable {
    private int age;
    private String name;
    private Department department;
    
    // Constructor, getters, and setters omitted for brevity
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        Employee cloned = (Employee) super.clone();
        // For deep copy, we need to clone reference types as well
        cloned.setDepartment((Department) this.department.clone());
        return cloned;
    }
}

public class Department implements Cloneable {
    private String name;
    private String location;
    
    // Constructor, getters, and setters omitted for brevity
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

In this example, a shallow copy would only clone primitive fields and references, while a deep copy would recursively clone all referenced objects as well.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.