Master Java Classes and Objects Fundamentals
Classes and Objects in Java
Classes and objects are the fundamental building blocks of Java programming. A class serves as a blueprint or template for creating objects, while objects are instances of classes that contain actual data and can perform actions.
What is a Class?
A class is a user-defined blueprint or prototype from which objects are created. It represents the set of properties or methods that are common to all objects of one type.
Class Structure
public class ClassName {
// Fields (instance variables)
private dataType fieldName;
// Constructor
public ClassName(parameters) {
// Initialization code
}
// Methods
public returnType methodName(parameters) {
// Method body
return value;
}
}
What is an Object?
An object is an instance of a class. When a class is defined, no memory is allocated until objects of that class are created. Objects have:
- State: Represented by attributes/fields
- Behavior: Represented by methods
- Identity: Unique identification
Class Definition Example
public class Student {
// Instance variables (fields)
private String name;
private int age;
private String studentId;
private double gpa;
// Default constructor
public Student() {
this.name = "Unknown";
this.age = 0;
this.studentId = "000000";
this.gpa = 0.0;
}
// Parameterized constructor
public Student(String name, int age, String studentId) {
this.name = name;
this.age = age;
this.studentId = studentId;
this.gpa = 0.0;
}
// Full constructor
public Student(String name, int age, String studentId, double gpa) {
this.name = name;
this.age = age;
this.studentId = studentId;
this.gpa = gpa;
}
// Getter methods
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getStudentId() {
return studentId;
}
public double getGpa() {
return gpa;
}
// Setter methods
public void setName(String name) {
if (name != null && !name.trim().isEmpty()) {
this.name = name;
}
}
public void setAge(int age) {
if (age >= 0 && age <= 120) {
this.age = age;
}
}
public void setGpa(double gpa) {
if (gpa >= 0.0 && gpa <= 4.0) {
this.gpa = gpa;
}
}
// Business methods
public void study(String subject) {
System.out.println(name + " is studying " + subject);
}
public boolean isHonorStudent() {
return gpa >= 3.5;
}
public String getGradeLevel() {
if (gpa >= 3.7) return "A";
else if (gpa >= 3.3) return "B+";
else if (gpa >= 3.0) return "B";
else if (gpa >= 2.7) return "C+";
else if (gpa >= 2.0) return "C";
else return "Below C";
}
// toString method for string representation
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", studentId='" + studentId + '\'' +
", gpa=" + gpa +
'}';
}
}
Object Creation and Usage
public class StudentDemo {
public static void main(String[] args) {
// Creating objects using different constructors
// Using default constructor
Student student1 = new Student();
System.out.println("Default student: " + student1);
// Using parameterized constructor
Student student2 = new Student("Alice Johnson", 20, "STU001");
System.out.println("Student 2: " + student2);
// Using full constructor
Student student3 = new Student("Bob Smith", 19, "STU002", 3.8);
System.out.println("Student 3: " + student3);
// Using setter methods
student1.setName("Charlie Brown");
student1.setAge(21);
student1.setGpa(3.2);
// Using getter methods
System.out.println("Student 1 name: " + student1.getName());
System.out.println("Student 1 GPA: " + student1.getGpa());
// Calling business methods
student2.study("Mathematics");
student3.study("Computer Science");
// Checking honor status
System.out.println(student2.getName() + " is honor student: " +
student2.isHonorStudent());
System.out.println(student3.getName() + " grade level: " +
student3.getGradeLevel());
}
}
Key Concepts
Instance Variables (Fields)
public class Car {
// Instance variables - each object has its own copy
private String brand;
private String model;
private int year;
private double price;
private boolean isRunning;
// These variables store the state of each car object
}
The this
Keyword
The this
keyword refers to the current object instance:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name; // this.name refers to instance variable
this.age = age; // age parameter shadows instance variable
}
public void setName(String name) {
this.name = name; // Distinguish between parameter and field
}
public Person getOlderPerson(Person other) {
if (this.age > other.age) {
return this; // Return current object
} else {
return other;
}
}
}
Method Overloading
Multiple methods with the same name but different parameters:
public class Calculator {
// Method overloading - same name, different parameters
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
public String add(String a, String b) {
return a + b;
}
}
Memory Management
Stack vs Heap
public class MemoryExample {
public static void main(String[] args) {
// Primitive variables stored in stack
int number = 10;
boolean flag = true;
// Object reference stored in stack, object data in heap
Student student = new Student("John", 20, "STU001");
// Multiple references can point to same object
Student anotherRef = student; // Both point to same object in heap
// Creating new object
Student student2 = new Student("Jane", 19, "STU002");
}
}
Object Lifecycle
- Creation: Memory allocated in heap
- Usage: Object methods called, state modified
- Garbage Collection: When no references exist, object is eligible for GC
Advanced Concepts
Object Initialization Block
public class Example {
private int value;
// Instance initialization block - runs before constructor
{
System.out.println("Instance initialization block");
value = 10;
}
// Static initialization block - runs once when class is loaded
static {
System.out.println("Static initialization block");
}
public Example() {
System.out.println("Constructor");
}
}
Nested Classes
public class OuterClass {
private int outerField = 10;
// Non-static nested class (inner class)
public class InnerClass {
public void display() {
System.out.println("Outer field: " + outerField);
}
}
// Static nested class
public static class StaticNestedClass {
public void display() {
System.out.println("Static nested class");
}
}
}
// Usage
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
Real-World Example: Library Management System
public class Book {
private String isbn;
private String title;
private String author;
private boolean isAvailable;
private String borrowerName;
private Date borrowDate;
public Book(String isbn, String title, String author) {
this.isbn = isbn;
this.title = title;
this.author = author;
this.isAvailable = true;
this.borrowerName = null;
this.borrowDate = null;
}
public boolean borrowBook(String borrowerName) {
if (isAvailable) {
this.isAvailable = false;
this.borrowerName = borrowerName;
this.borrowDate = new Date();
System.out.println("Book '" + title + "' borrowed by " + borrowerName);
return true;
} else {
System.out.println("Book '" + title + "' is not available");
return false;
}
}
public void returnBook() {
if (!isAvailable) {
System.out.println("Book '" + title + "' returned by " + borrowerName);
this.isAvailable = true;
this.borrowerName = null;
this.borrowDate = null;
} else {
System.out.println("Book '" + title + "' was not borrowed");
}
}
public void displayInfo() {
System.out.println("ISBN: " + isbn);
System.out.println("Title: " + title);
System.out.println("Author: " + author);
System.out.println("Available: " + isAvailable);
if (!isAvailable) {
System.out.println("Borrowed by: " + borrowerName);
System.out.println("Borrow date: " + borrowDate);
}
}
// Getters
public String getIsbn() { return isbn; }
public String getTitle() { return title; }
public String getAuthor() { return author; }
public boolean isAvailable() { return isAvailable; }
}
// Usage example
public class LibraryDemo {
public static void main(String[] args) {
// Creating book objects
Book book1 = new Book("978-0134685991", "Effective Java", "Joshua Bloch");
Book book2 = new Book("978-0135166307", "Java: The Complete Reference", "Herbert Schildt");
// Display book information
book1.displayInfo();
System.out.println();
// Borrow books
book1.borrowBook("Alice Smith");
book2.borrowBook("Bob Johnson");
System.out.println();
// Try to borrow already borrowed book
book1.borrowBook("Charlie Brown");
System.out.println();
// Return book
book1.returnBook();
// Borrow again
book1.borrowBook("Charlie Brown");
}
}
Best Practices
Class Design
public class WellDesignedClass {
// 1. Use private fields for encapsulation
private String name;
private int value;
// 2. Provide constructors for object initialization
public WellDesignedClass(String name, int value) {
setName(name); // Use setter for validation
setValue(value);
}
// 3. Validate input in setters
public void setName(String name) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name cannot be null or empty");
}
this.name = name;
}
public void setValue(int value) {
if (value < 0) {
throw new IllegalArgumentException("Value cannot be negative");
}
this.value = value;
}
// 4. Provide meaningful getters
public String getName() {
return name;
}
public int getValue() {
return value;
}
// 5. Override toString() for debugging
@Override
public String toString() {
return "WellDesignedClass{name='" + name + "', value=" + value + "}";
}
// 6. Override equals() and hashCode() when needed
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
WellDesignedClass that = (WellDesignedClass) obj;
return value == that.value && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, value);
}
}
Common Mistakes to Avoid
Making all fields public
// Bad public class BadClass { public String name; // Direct access, no validation public int age; } // Good public class GoodClass { private String name; // Encapsulated private int age; public void setAge(int age) { if (age >= 0) this.age = age; // Validation } }
Not providing constructors
// Bad - relying only on default constructor Student student = new Student(); student.setName("John"); // Multiple method calls needed student.setAge(20); // Good - parameterized constructor Student student = new Student("John", 20, "STU001");
Not validating input
// Bad public void setAge(int age) { this.age = age; // No validation } // Good public void setAge(int age) { if (age < 0 || age > 150) { throw new IllegalArgumentException("Invalid age: " + age); } this.age = age; }
Summary
- Classes are blueprints that define the structure and behavior of objects
- Objects are instances of classes that contain actual data and state
- Use encapsulation to protect data with private fields and public methods
- Constructors initialize objects when they are created
- The
this
keyword refers to the current object instance - Method overloading allows multiple methods with the same name but different parameters
- Follow best practices for class design to create maintainable and robust code
Understanding classes and objects is fundamental to Java programming and forms the foundation for all other object-oriented concepts.