Introduction to Object-Oriented Programming (OOP)
- Object-Oriented Programming (OOP) is a paradigm where everything is considered as an object. The fundamental building blocks include:
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
- Pure object-oriented languages follow this principle strictly — everything, even primitives like integers and booleans, is considered as an object.
- Pure OOP Language Examples:
- Smalltalk
- Ruby (to a large extent)
- Eiffel
Principles of Pure Object-Oriented Languages
- A pure OOP language must satisfy:
- Everything is an object.
- All operations are performed by sending messages to objects.
- All values are objects.
- Programs are composed exclusively of objects and their interactions.
Overview of Java and Its Object-Oriented Nature
- Java is mostly object-oriented but not purely. It supports most OOP features but includes certain elements that violate the strict definitions of pure OOP.
Example:
int a = 10; // Not an object
String s = "Hello"; // Object
Here, int is not an object, which contradicts pure OOP.
Primitive Data Types in Java
- Java has 8 primitive data types:
- byte, short, int, long
- float, double
- char
- boolean
These are not objects.
- Example:
int x = 5;
Here, x is a primitive type, not an instance of a class. In pure OOP, even numbers would be objects.
Static Members and Their Implications
- Java allows static methods and variables that belong to the class and not to objects.
Example:
class Example {
static int count = 0;
static void showCount() {
System.out.println(count);
}
}
You can call:
Example.showCount();
- This bypasses the need for an object — violating the "everything is object" rule.
Use of this and super Keywords
- Although Java supports object references like this and super, they work in specific contexts, and don’t enforce object usage in static scenarios.
class Parent {
void display() {
System.out.println("Parent");
}
}
class Child extends Parent {
void show() {
super.display(); // calls Parent method
}
}
super supports inheritance but doesn't make static usage object-oriented.
Support for Procedural Programming
- Java permits procedural-style code inside static methods like main().
public class Main {
public static void main(String[] args) {
int sum = 0;
for(int i=0; i<10; i++) {
sum += i;
}
System.out.println(sum);
}
}
This looks similar to C — procedural and not object-oriented.
Wrapper Classes: A Bridge Between Primitive and Object
- Java provides wrapper classes for primitives:
Primitive | Wrapper Class |
---|---|
int | Integer |
float | Float |
char | Character |
Example:
int a = 10;
Integer obj = new Integer(a); // Object wrapping
Still, the use of wrappers is optional, and primitive types are more efficient and commonly used.
Absence of Operator Overloading
- In Java, you cannot overload operators (except + for strings). Pure OOP languages allow this for object behavior customization.
Example:
class Complex {
int real, imag;
// No way to overload + operator like in C++
}
Access to Static Context Without Objects
- Static variables and methods can be accessed without creating any object.
Example:
Math.sqrt(16); // No Math object created
Math methods are static — procedural style, not object-oriented.
Role of main() Method in Java
- Java requires a static main() to start execution.
public static void main(String[] args) { }
This method runs without an object, violating the pure OOP principle.
Lack of Multiple Inheritance via Classes
- Java does not support multiple inheritance via classes — a key object-oriented feature.
Example (Illegal in Java):
class A { }
class B { }
class C extends A, B { } // Error
Java resolves this using interfaces, not direct class inheritance.
Autoboxing and Unboxing Mechanism
- Java introduced autoboxing to ease primitive–object interaction:
Integer x = 5; // auto-boxing
int y = x; // auto-unboxing
But this is a workaround, not a core OOP feature.
Final Variables and Methods
- The use of final restricts polymorphism:
final class A { }
class B extends A { } // Error
This breaks extensibility — a key OOP trait.
Use of instanceof Keyword
- Java checks object types at runtime:
if (obj instanceof String) {
System.out.println("It's a string.");
}
This type-checking indicates reliance on non-OOP constructs like type testing.
Interfaces and Functional Programming
- Functional interfaces (Runnable, Callable, etc.) are used as behavioral contracts, but they introduce functional, not object-based logic.
Runnable r = () -> System.out.println("Run");
Native Methods in Java
- Java can call native code written in C/C++ using native keyword.
- public native void nativeMethod();
- These methods operate outside the JVM, beyond the object model of Java.
Type System and Type Safety
- Java's static typing imposes restrictions that don't always align with object flexibility (dynamic behavior in pure OOP).
Object Creation Outside of Class
- You can create an object in any method or context, not necessarily in class-specific methods.
- Employee e = new Employee();
- This loose coupling sometimes leads to procedural style.
Arrays and Object-Oriented Nature
- Java arrays are objects, but their handling often resembles procedural languages:
- You manipulate arrays with loops and indexes, not with object behaviors.
Anonymous and Inner Classes
- Inner classes may violate the class-per-file rule, and while powerful, sometimes reduce clarity of the object model.
Runnable r = new Runnable() {
public void run() {
System.out.println("Running...");
}
};
Java and Object Serialization
- Java supports object serialization, but primitives in objects are treated differently during serialization.
Reflection API and Class Manipulation
- Reflection allows inspection of classes, methods, fields — sometimes violating encapsulation.
Class c = Class.forName("java.lang.String");
Reflection breaks abstraction — a key pillar of OOP.
Functional Interfaces and Lambda Expressions
- Lambdas in Java are not true objects but are converted to functional interfaces at runtime.
- Function<Integer, Integer> square = x -> x * x;
- This leans toward functional programming, diverging from pure OOP.
Conclusion
- Java is an object-based but not pure object-oriented language. While it supports key OOP concepts like classes, inheritance, and polymorphism, it also:
- Has primitive types
- Supports static contexts
- Allows procedural code
- Lacks multiple inheritance via classes
- Uses native methods and non-OOP constructs
Summary:
Feature | Pure OOP? | Java Support |
---|---|---|
Everything is Object | ✅ | ✅ |
Primitive Data Types | ✅ | ✅ |
Static Methods | ✅ | ✅ |
Multiple Inheritance | ✅ | ✅ |
Operator Overloading | ✅ | ✅ |
Procedural Support | ✅ | ✅ |
Final Thought:
- Java strikes a balance between performance and OOP purity. It sacrifices complete object-orientation for practicality and speed, making it versatile — but not pure.
Also Read:
0 Comments