L10: Introduction to Writing Classes Pt.1

Overview

In this chapter, we’ll dive into the fundamentals of writing classes in Java, focusing on how to design and implement basic class structures, how to identify and declare instance variables, and how to write constructors and methods. By the end of this guide, you’ll have a clear understanding of how to build reusable, modular classes that encapsulate data and behavior effectively.

Introduction

Classes form the backbone of Java’s object-oriented programming (OOP). They allow you to create reusable blueprints to represent complex concepts, tying data and behaviors together. While we’ve previously worked with client classes like Scanner and String, those were built-in classes. The goal now is to create our own custom classes, also called instantiable classes, where we define both the data (state) and behaviors (actions) ourselves.

Key Points:

  • Modularity: Classes encapsulate functionality, making code reusable and easier to maintain.
  • Customization: Writing custom classes allows for more control over how objects behave compared to using predefined classes.

Identifying Data and Behaviors

Before writing a class, you need to determine:

  1. Data (Attributes/State): These are the properties of an object.
  2. Behaviors (Methods): These are the actions that the object can perform.

For example, let’s build a class for an insect. The attributes of the insect could include its weight, and its position in the world (x and y coordinates). Its behaviors might include move and eat.

public class Insect {
    private double weight;  // Data
    private int x, y;       // Data

    public void move() {    // Behavior
        // Method logic for moving
    }

    public void eat() {     // Behavior
        // Method logic for eating
    }
}

Instance Variables

Instance variables store the state of an object. Each object of a class has its own copy of these variables. This means that every instance of the Insect class has its own values for weight, x, and y.

Instance variables are declared at the class level, outside any methods, making them accessible to all methods of the class.

public class Insect {
    private double weight;  // Instance variable
    private int x, y;       // Instance variable
}

In memory, each object gets its own space in the heap, where it stores its instance variables.

Heap Memory
┌────────────────────────────────────────────────────┐
│ Insect 1 (Object Reference)                         │
│ ┌───────────┐   ┌────────────┐   ┌───────────┐      │
│ │ weight: 5 │   │ x: 10      │   │ y: 20     │      │
│ └───────────┘   └────────────┘   └───────────┘      │
│                                                    │
│ Insect 2 (Object Reference)                         │
│ ┌───────────┐   ┌────────────┐   ┌───────────┐      │
│ │ weight: 3 │   │ x: 15      │   │ y: 25     │      │
│ └───────────┘   └────────────┘   └───────────┘      │
│                                                    │
│ Insect 3 (Object Reference)                         │
│ ┌───────────┐   ┌────────────┐   ┌───────────┐      │
│ │ weight: 8 │   │ x: 12      │   │ y: 30     │      │
│ └───────────┘   └────────────┘   └───────────┘      │
└────────────────────────────────────────────────────┘
classDiagram
  class Insect {
    -double weight
    -int x
    -int y
    +move()
    +eat()
  }

Visibility Modifiers (public and private)

Visibility modifiers control access to class members (variables and methods). In Java, the two most common visibility modifiers are:

  • private: Members can only be accessed within the same class.
  • public: Members can be accessed from other classes.
public class Insect {
    private double weight; // Only accessible within Insect
    public void move() {   // Accessible to other classes
        // Move logic
    }
}

The principle of encapsulation ensures that an object controls its own state. By making instance variables private, you ensure that external classes cannot directly manipulate an object’s state.

Testing Objects

To create an object, use a client class or add a main method directly in your class.

public class TestInsect {
    public static void main(String[] args) {
        Insect bee = new Insect();  // Create an Insect object
        bee.move();                 // Call method
    }
}

Constructors

A constructor is a special method that initializes a new object. Every time an object is created, its constructor is called. Java provides a default constructor if none is defined, but you can also create custom constructors to initialize variables with specific values.

Default Constructor

public class Insect {
    public Insect() {
        // Default constructor
        weight = 1.0;  // Default weight
        x = 0;         // Default x-coordinate
        y = 0;         // Default y-coordinate
    }
}

Custom Constructor

public class Insect {
    public Insect(double initialWeight, int startX, int startY) {
        weight = initialWeight;  // Set initial weight
        x = startX;              // Set initial x-coordinate
        y = startY;              // Set initial y-coordinate
    }
}

Methods

Methods define the behaviors of an object. Methods can either manipulate the state (non-static) or provide utility functionality (static). In our Insect class, move() and eat() are examples of methods.

public void move() {
    // Logic to change x and y coordinates
}

public void eat() {
    // Logic to increase weight
}

Static Variables and Constants

Static variables are shared across all instances of a class, meaning there is only one copy in memory. Constants are defined using the final keyword.

public class Insect {
    private static final double MAX_WEIGHT = 100.0;  // Constant
}

More on Static Methods

Static methods belong to the class rather than instances of the class. For example, a utility method to generate random values can be static.

public static int getRandomCoordinate() {
    return (int)(Math.random() * 100);  // Generate random coordinate
}

Knowledge Check

  1. What is an instance variable?
    An instance variable is a variable defined at the class level and is specific to each instance (or object) of the class. Each object of the class has its own unique copy of the instance variables, which hold the object’s state or attributes.
  2. What does the private visibility modifier do?
    The private visibility modifier restricts access to a class member (variable or method) so that it can only be accessed within the same class. It prevents external classes from directly accessing or modifying the member, helping to encapsulate the class’s internal state.
  3. How are static methods different from non-static methods?
    Static methods belong to the class itself, not to any specific instance of the class. They can be called without creating an object of the class and typically provide utility functions. Non-static methods, on the other hand, operate on individual objects and can access instance variables specific to the object.
  4. Why do we use constructors in a class?
    Constructors are used to initialize the state of an object when it is created. They set the initial values of the instance variables and ensure that the object is in a valid state when it starts being used.
  5. Can you write a constructor with parameters?
    Yes, a constructor can accept parameters to set initial values.
  6. What are instance variables?
    Instance variables are variables declared at the class level, specific to each object of the class.
  7. Why should instance variables be private?
    To protect the internal state of objects and ensure that only methods within the class can modify them.

Extra Resources