1. Class Definition and Object Creation
Java:
public class Car {
// Fields (attributes)
private String color;
private String model;
private int year;
// Constructor
public Car(String color, String model, int year) {
this.color = color;
this.model = model;
this.year = year;
}
// Method
public void displayInfo() {
System.out.println(model + " (" + year + ") - " + color);
}
}
// Creating object
Car myCar = new Car("Red", "Tesla", 2023);
myCar.displayInfo();
Python:
class Car:
# Constructor (initializer)
def __init__(self, color, model, year):
self.color = color
self.model = model
self.year = year
# Method
def display_info(self):
print(f"{self.model} ({self.year}) - {self.color}")
# Creating object
my_car = Car("Red", "Tesla", 2023)
my_car.display_info()
Key Differences:
- Java requires explicit field declarations with types; Python defines attributes dynamically in
__init__. - Java uses
newkeyword; Python doesn't. - Java uses
this; Python usesself(explicitly required as first parameter). - Python's
__init__is similar to Java constructors but technically different.
2. Access Modifiers and Encapsulation
Java:
public class BankAccount {
private double balance; // Private field
public BankAccount(double initialBalance) {
this.balance = initialBalance;
}
// Getter
public double getBalance() {
return balance;
}
// Setter with validation
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
private void auditLog() { // Private method
System.out.println("Logging transaction");
}
}
BankAccount account = new BankAccount(1000);
// account.balance = 5000; // Error: balance is private
account.deposit(500);
System.out.println(account.getBalance()); // 1500
Python:
class BankAccount:
def __init__(self, initial_balance):
self.__balance = initial_balance # "Private" (name mangling)
# Getter
def get_balance(self):
return self.__balance
# Setter with validation
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def __audit_log(self): # "Private" method
print("Logging transaction")
account = BankAccount(1000)
account.deposit(500)
print(account.get_balance()) # 1500
# Can still access (but discouraged):
# print(account._BankAccount__balance) # Name mangling
Python Properties (More Pythonic):
class BankAccount:
def __init__(self, initial_balance):
self._balance = initial_balance # Convention: single underscore = "protected"
@property
def balance(self): # Getter
return self._balance
@balance.setter
def balance(self, amount): # Setter
if amount >= 0:
self._balance = amount
account = BankAccount(1000)
print(account.balance) # Uses getter
account.balance = 1500 # Uses setter
Key Differences:
- Java has strict access modifiers (
public,private,protected, package-private). - Python uses naming conventions:
_protected,__private(name mangling). - Python's encapsulation is convention-based, relying on developer cooperation.
3. Inheritance
Single Inheritance
Java:
// Parent class
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
}
// Child class
class Dog extends Animal {
public Dog(String name) {
super(name); // Call parent constructor
}
public void bark() {
System.out.println(name + " is barking");
}
}
Dog dog = new Dog("Buddy");
dog.eat(); // Inherited method
dog.bark(); // Own method
Python:
# Parent class
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name} is eating")
# Child class
class Dog(Animal):
def __init__(self, name):
super().__init__(name) # Call parent constructor
def bark(self):
print(f"{self.name} is barking")
dog = Dog("Buddy")
dog.eat() # Inherited method
dog.bark() # Own method
Multiple Inheritance
Java (Not Supported for Classes):
// Java uses interfaces for multiple inheritance
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
public void fly() {
System.out.println("Duck is flying");
}
public void swim() {
System.out.println("Duck is swimming");
}
}
Duck duck = new Duck();
duck.fly();
duck.swim();
Python (Fully Supported):
class Flyable:
def fly(self):
print("Flying")
class Swimmable:
def swim(self):
print("Swimming")
class Duck(Flyable, Swimmable): # Multiple inheritance
pass
duck = Duck()
duck.fly()
duck.swim()
Key Differences:
- Python supports multiple inheritance directly; Java does not (uses interfaces instead).
- Python uses Method Resolution Order (MRO) via C3 linearization to handle diamond problem.
- Java avoids diamond problem by not allowing multiple class inheritance.
4. Method Overriding and Polymorphism
Java:
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override // Optional annotation
public void makeSound() {
System.out.println("Bark");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
// Polymorphism
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.makeSound(); // Bark
myCat.makeSound(); // Meow
Python:
class Animal:
def make_sound(self):
print("Animal sound")
class Dog(Animal):
def make_sound(self): # Override
print("Bark")
class Cat(Animal):
def make_sound(self): # Override
print("Meow")
# Polymorphism (duck typing)
my_dog = Dog()
my_cat = Cat()
my_dog.make_sound() # Bark
my_cat.make_sound() # Meow
# Duck typing example
def animal_sound(animal):
animal.make_sound() # No type checking needed
animal_sound(my_dog) # Bark
animal_sound(my_cat) # Meow
Key Difference:
- Python uses duck typing: "If it walks like a duck and quacks like a duck, it's a duck".
- Java uses static typing with explicit type declarations.
5. Abstract Classes and Interfaces
Java:
// Abstract class
abstract class Shape {
abstract double area(); // Abstract method
public void display() { // Concrete method
System.out.println("Area: " + area());
}
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
// Interface
interface Drawable {
void draw();
}
class Rectangle extends Shape implements Drawable {
private double width, height;
public Rectangle(double w, double h) {
width = w;
height = h;
}
@Override
double area() {
return width * height;
}
@Override
public void draw() {
System.out.println("Drawing rectangle");
}
}
Python:
from abc import ABC, abstractmethod
# Abstract class
class Shape(ABC):
@abstractmethod
def area(self): # Abstract method
pass
def display(self): # Concrete method
print(f"Area: {self.area()}")
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
circle = Circle(5)
circle.display() # Area: 78.5
6. Static Methods and Class Methods
Java:
class MathUtils {
// Static method
public static int add(int a, int b) {
return a + b;
}
}
// Call without creating instance
int result = MathUtils.add(5, 3); // 8
Python:
class MathUtils:
# Static method
@staticmethod
def add(a, b):
return a + b
# Class method
@classmethod
def multiply(cls, a, b):
return a * b
# Call without creating instance
result = MathUtils.add(5, 3) # 8
result2 = MathUtils.multiply(4, 2) # 8
7. Constructor Overloading
Java:
class Person {
private String name;
private int age;
// Constructor 1
public Person(String name) {
this.name = name;
this.age = 0;
}
// Constructor 2 (overloaded)
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Person p1 = new Person("Alice");
Person p2 = new Person("Bob", 30);
Python:
class Person:
def __init__(self, name, age=0): # Default parameter
self.name = name
self.age = age
p1 = Person("Alice")
p2 = Person("Bob", 30)
Key Difference:
- Java supports constructor overloading.
- Python uses default arguments instead (only one
__init__allowed).
8. Practical Example: Complete Class
Java:
public class Employee {
private String name;
private double salary;
private static int employeeCount = 0;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
employeeCount++;
}
public void giveRaise(double percentage) {
salary += salary * (percentage / 100);
}
public static int getEmployeeCount() {
return employeeCount;
}
@Override
public String toString() {
return name + ": $" + salary;
}
}
Employee emp1 = new Employee("Alice", 50000);
emp1.giveRaise(10);
System.out.println(emp1); // Alice: $55000.0
System.out.println(Employee.getEmployeeCount()); // 1
Python:
class Employee:
employee_count = 0 # Class variable
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.employee_count += 1
def give_raise(self, percentage):
self.salary += self.salary * (percentage / 100)
@classmethod
def get_employee_count(cls):
return cls.employee_count
def __str__(self): # Similar to toString()
return f"{self.name}: ${self.salary}"
emp1 = Employee("Alice", 50000)
emp1.give_raise(10)
print(emp1) # Alice: $55000.0
print(Employee.get_employee_count()) # 1
Summary Table
-
Class Definition
- Java: Explicit field declarations
- Python: Dynamic attributes in
__init__
-
Access Modifiers
- Java:
public,private,protected(strict) - Python: Convention-based (
_,__)
- Java:
-
Inheritance
- Java: Single inheritance only (+ interfaces)
- Python: Multiple inheritance supported
-
Constructor
- Java: Method with class name, can be overloaded
- Python:
__init__method, use default params
-
Static Methods
- Java:
statickeyword - Python:
@staticmethoddecorator
- Java:
-
Abstract Classes
- Java:
abstractkeyword - Python:
ABCmodule with@abstractmethod
- Java:
-
Method Reference
- Java:
this(implicit) - Python:
self(explicit first parameter)
- Java:
-
Polymorphism
- Java: Type-based
- Python: Duck typing
-
Object Creation
- Java:
newkeyword required - Python: Direct class call
- Java: