Java Classes
Introduction
Java classes are the foundation of Object-Oriented Programming (OOP) in Java. They serve as blueprints for creating objects, which are instances of these classes. Understanding classes is essential before diving into Spring Framework development, as Spring heavily relies on Java's object-oriented features.
In this tutorial, we'll explore what Java classes are, how to create them, and how they're used in real-world applications. We'll also cover important concepts like constructors, methods, properties, and access modifiers.
What is a Java Class?
A Java class is a blueprint or template that defines the data (attributes) and behavior (methods) that objects of that class will have. Think of a class as a "cookie cutter" and objects as the "cookies" made from that cutter.
Here's the basic structure of a Java class:
public class ClassName {
// Fields (attributes)
// Constructors
// Methods (behaviors)
}
Creating Your First Class
Let's create a simple Person
class to understand the concept:
public class Person {
// Fields or attributes
String name;
int age;
// Constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Method
public void introduce() {
System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
}
}
To use this class, we need to create objects (instances) of it:
public class Main {
public static void main(String[] args) {
// Create objects of Person class
Person person1 = new Person("John", 30);
Person person2 = new Person("Sarah", 25);
// Call methods on these objects
person1.introduce();
person2.introduce();
}
}
Output:
Hello, my name is John and I am 30 years old.
Hello, my name is Sarah and I am 25 years old.
Class Components in Detail
Fields (Attributes/Properties)
Fields are variables declared inside a class. They represent the state or attributes of objects created from the class.
public class Car {
// Fields
String model;
String color;
int year;
double price;
}
Constructors
Constructors are special methods used to initialize objects. They have the same name as the class and don't have a return type.
public class Car {
String model;
String color;
int year;
// Default constructor
public Car() {
model = "Unknown";
color = "White";
year = 2023;
}
// Parameterized constructor
public Car(String model, String color, int year) {
this.model = model;
this.color = color;
this.year = year;
}
}
You can create objects using either constructor:
Car defaultCar = new Car(); // Uses default constructor
Car customCar = new Car("Tesla", "Red", 2023); // Uses parameterized constructor
Methods
Methods define the behavior of objects. They can perform operations, manipulate data, and return values.
public class Calculator {
// Method that returns a value
public int add(int a, int b) {
return a + b;
}
// Method that doesn't return a value (void)
public void displayResult(String operation, int result) {
System.out.println(operation + " result: " + result);
}
// Static method (belongs to the class, not objects)
public static int multiply(int a, int b) {
return a * b;
}
}
Usage example:
Calculator calc = new Calculator();
int sum = calc.add(5, 3);
calc.displayResult("Addition", sum);
// Static method can be called without creating an object
int product = Calculator.multiply(4, 6);
System.out.println("Multiplication result: " + product);
Output:
Addition result: 8
Multiplication result: 24
Access Modifiers
Java provides access modifiers to control the visibility of classes, methods, and fields:
public
: Accessible from anywhereprivate
: Accessible only within the same classprotected
: Accessible within the same package and by subclasses- Default (no modifier): Accessible only within the same package
Here's an example:
public class Student {
// Public field - accessible from anywhere
public String name;
// Private field - only accessible within this class
private int id;
// Protected field - accessible in same package and subclasses
protected int age;
// Default field - accessible only in same package
String grade;
// Public method
public void setId(int id) {
this.id = id;
}
// Private method
private void generateId() {
// Some implementation
}
}
Getters and Setters
It's a best practice to make fields private and provide public methods (getters and setters) to access and modify them:
public class BankAccount {
private String accountNumber;
private double balance;
// Constructor
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// Getter for accountNumber
public String getAccountNumber() {
return accountNumber;
}
// Balance getter
public double getBalance() {
return balance;
}
// We don't provide a setter for accountNumber as we don't want it to change
// Deposit method instead of direct setter for balance
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: $" + amount);
} else {
System.out.println("Invalid deposit amount");
}
}
// Withdraw method
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: $" + amount);
} else {
System.out.println("Invalid withdrawal amount or insufficient funds");
}
}
}
Using the BankAccount
class:
public class BankDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount("123456789", 1000.0);
System.out.println("Account: " + account.getAccountNumber());
System.out.println("Initial balance: $" + account.getBalance());
account.deposit(500.0);
account.withdraw(200.0);
System.out.println("Current balance: $" + account.getBalance());
// This would fail
account.withdraw(2000.0);
}
}
Output:
Account: 123456789
Initial balance: $1000.0
Deposited: $500.0
Withdrawn: $200.0
Current balance: $1300.0
Invalid withdrawal amount or insufficient funds
The this
Keyword
The this
keyword refers to the current object. It's often used to distinguish between instance variables and parameters with the same name:
public class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
// Using 'this' to refer to instance variables
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
}
Static Members
Static fields and methods belong to the class rather than to objects:
public class MathUtils {
// Static constant
public static final double PI = 3.14159;
// Static variable
private static int operationsPerformed = 0;
// Static method
public static double calculateCircleArea(double radius) {
operationsPerformed++;
return PI * radius * radius;
}
// Static method to access the static variable
public static int getOperationsPerformed() {
return operationsPerformed;
}
}
Usage example:
public class StaticDemo {
public static void main(String[] args) {
// No need to create objects
double area1 = MathUtils.calculateCircleArea(5);
double area2 = MathUtils.calculateCircleArea(7);
System.out.println("Circle 1 area: " + area1);
System.out.println("Circle 2 area: " + area2);
System.out.println("Operations performed: " + MathUtils.getOperationsPerformed());
}
}
Output:
Circle 1 area: 78.53975
Circle 2 area: 153.93791
Operations performed: 2
Real-World Example: Building a Product Class for E-Commerce
Let's create a more comprehensive example of a class that could be used in a real-world Spring application for an e-commerce system:
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
public class Product {
// Fields with appropriate access modifiers
private UUID id;
private String name;
private String description;
private BigDecimal price;
private int stockQuantity;
private String category;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
// Constructors
public Product() {
this.id = UUID.randomUUID();
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
public Product(String name, String description, BigDecimal price, int stockQuantity, String category) {
this(); // Call the default constructor first
this.name = name;
this.description = description;
this.price = price;
this.stockQuantity = stockQuantity;
this.category = category;
}
// Getters and Setters
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
this.updateTimestamp();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
this.updateTimestamp();
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
if (price.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Price cannot be negative");
}
this.price = price;
this.updateTimestamp();
}
public int getStockQuantity() {
return stockQuantity;
}
public void setStockQuantity(int stockQuantity) {
if (stockQuantity < 0) {
throw new IllegalArgumentException("Stock quantity cannot be negative");
}
this.stockQuantity = stockQuantity;
this.updateTimestamp();
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
this.updateTimestamp();
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
// Business methods
public boolean isInStock() {
return stockQuantity > 0;
}
public boolean canOrder(int quantity) {
return quantity > 0 && quantity <= stockQuantity;
}
public void reduceStock(int quantity) {
if (!canOrder(quantity)) {
throw new IllegalArgumentException("Cannot order " + quantity + " units");
}
this.stockQuantity -= quantity;
this.updateTimestamp();
}
public BigDecimal calculateTotalPrice(int quantity) {
if (quantity <= 0) {
throw new IllegalArgumentException("Quantity must be positive");
}
return this.price.multiply(new BigDecimal(quantity));
}
// Helper methods
private void updateTimestamp() {
this.updatedAt = LocalDateTime.now();
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
", stockQuantity=" + stockQuantity +
", category='" + category + '\'' +
'}';
}
}
Using the Product
class:
import java.math.BigDecimal;
public class ECommerceDemo {
public static void main(String[] args) {
// Create a new product
Product laptop = new Product(
"Dell XPS 15",
"15-inch premium laptop with Intel i7, 16GB RAM, and 512GB SSD",
new BigDecimal("1299.99"),
50,
"Electronics"
);
// Display product information
System.out.println("Product: " + laptop.getName());
System.out.println("Price: $" + laptop.getPrice());
System.out.println("In stock: " + (laptop.isInStock() ? "Yes" : "No"));
// Perform a purchase
int orderQuantity = 2;
if (laptop.canOrder(orderQuantity)) {
BigDecimal totalPrice = laptop.calculateTotalPrice(orderQuantity);
laptop.reduceStock(orderQuantity);
System.out.println("\nOrder placed:");
System.out.println("Quantity: " + orderQuantity);
System.out.println("Total price: $" + totalPrice);
System.out.println("Remaining stock: " + laptop.getStockQuantity());
}
// Updated product information
System.out.println("\nUpdated product information:");
System.out.println(laptop);
}
}
Output:
Product: Dell XPS 15
Price: $1299.99
In stock: Yes
Order placed:
Quantity: 2
Total price: $2599.98
Remaining stock: 48
Updated product information:
Product{id=a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6, name='Dell XPS 15', price=1299.99, stockQuantity=48, category='Electronics'}
Classes in Spring Context
In Spring applications, classes typically represent:
- Entities: Model objects that map to database tables
- DTOs (Data Transfer Objects): Objects to transfer data between layers
- Services: Classes containing business logic
- Controllers: Classes handling HTTP requests
- Repositories: Classes for data access
For example, our Product
class might be used as an entity in a Spring application:
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
// Other imports...
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
private String name;
private String description;
private BigDecimal price;
private int stockQuantity;
private String category;
// Constructors, getters, setters, and methods as before
}
Summary
Java classes are the building blocks of object-oriented programming and form the foundation for Spring applications. In this tutorial, we've covered:
- Creating classes and objects
- Fields and methods
- Constructors for object initialization
- Access modifiers to control visibility
- Getters and setters for encapsulation
- Static members
- A real-world example of a class
Understanding Java classes is crucial for Spring development, as Spring is built on object-oriented principles and extensively uses classes for various components like controllers, services, repositories, and entities.
Practice Exercises
-
Basic: Create a
Book
class with fields for title, author, ISBN, and pages. Include appropriate constructors, getters, and setters. -
Intermediate: Create a
LibrarySystem
with two classes:Book
andLibrary
. Implement methods for adding books to the library, borrowing, and returning books. -
Advanced: Create an e-commerce system with classes for
Product
,ShoppingCart
, andOrder
. Implement methods for adding products to the cart and processing orders.
Additional Resources
- Oracle's Java Tutorial on Classes and Objects
- Object-Oriented Programming Concepts
- JavaPoints on Java Classes and Objects
Happy coding with Java classes!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)