Unit 2: Using Objects

Understanding Java Classes


Introduction to Classes in Java

Java classes are the building blocks of object-oriented programming. They are the blueprint or prototype for creating objects, encapsulating data and behaviors in a unified structure. Classes are declared with the class keyword, and they can be instantiated to create objects.

Definition: Classes in Java are the blueprint or prototype for creating objects, encapsulating data and behaviors in a unified structure.


The Structure of a Class

Class Declaration

Classes in Java are declared with the class keyword, followed by the class name, and enclosed in curly braces. The class name should be in Pascal case, and the file name should match the class name. The class body contains the class members, including instance variables, methods, constructors, and nested classes or interfaces.

public class Car {
  // class members
}

Class Keyword

The class keyword is used to declare a class in Java. It is followed by the class name and enclosed in curly braces. The class name should be in Pascal case, and the file name should match the class name.

// file name: Vehicle.java
public class Vehicle {
  // class members
  public static void main(String[] args) {
    // main method
  }

  public void drive() {
    // drive method
    System.out.println("Driving...");
  }
}

Class Name

Conventionally starts with an uppercase letter. Should be in Pascal case.

public class VehicleAppraiser {
  // class members
}

Class Components

Classes contain the following components:

  • Properties (instance variables)
  • Methods
  • Constructors
  • Nested classes or interfaces

Instance Variables

Instance variables are declared in a class but outside a method and are used to represent object-specific data.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;
}

Static Variables

Static variables are declared in a class but outside a method and are used to represent class-specific data.

public class Car {
  // static variables
  static int numberOfCars;
}

The difference between instance and static variables

The difference between instance variables and static variables is that instance variables are unique to each object, while static variables are shared across all objects of the class.


Methods and Functions Explained

Methods are declared with a return type, method name, and parameters. They represent behaviors or actions.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // methods
  public void drive() {
    System.out.println("Driving...");
  }
}

Methods and Functions

Methods are just functions that belong to a class. Functions are declared outside of a class, while methods are declared inside a class.

Methods and Functions

In Java, the terms "method" and "function" are often used interchangeably by newcomers, but within the context of the language, the term "function" isn't explicitly used as it is in some other languages. Java is primarily an object-oriented programming (OOP) language, and because of this, most "functions" are actually methods that belong to classes.

Let's break down the concepts:

Method:

A method is a block of code that performs a specific task and is defined inside a class or interface.

In Java, you can't have standalone methods that aren't part of a class (or interface). Methods can have access modifiers like public, private, protected, or package-private (default). They can be instance methods (requiring an object of the class to be invoked) or static methods (can be invoked on the class itself without needing an object). Example:

// Here, sayHello is a method.
public class HelloWorld {
public void sayHello() {
System.out.println("Hello, World!");
}
}

Function:

In many programming languages, a function is a self-contained block of code that encapsulates functionality. You can give input to a function, and it can return a value.

Java doesn't really have "functions" in the standalone sense like languages such as C or JavaScript. However, with the introduction of lambdas in Java 8 and the java.util.function package, the functional programming paradigm became more pronounced in Java. While Java introduced more functional programming capabilities, the term "function" still isn't explicitly used in the language's formal definition. Instead, you might hear terms like "functional interface" or "lambda function", but they are still typically related to object-oriented structures.

Example of a function in Java:

Function<String, Integer> stringLengthFunction = str -> str.length();
int length = stringLengthFunction.apply("Hello");

Methods are blocks of code associated with an object (instance methods) or a class (static methods).

The term "function" isn't used in traditional Java OOP, but with the introduction of lambdas and functional programming constructs, "function" or "lambda function" can refer to pieces of functionality that can be passed around as first-class citizens. However, even these are closely tied to the OOP nature of Java, often being represented as methods of functional interfaces.


Constructors: Bringing Objects to Life

Constructors

Constructors are special methods used to initialize objects. They are invoked using the new keyword when creating an object. They are declared with the same name as the class and can be overloaded.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }
}

Constructors

Constructors are special methods used to initialize objects. They are invoked using the new keyword when creating an object. They are declared with the same name as the class and can be overloaded.

Role

Constructors are used to initialize objects. They are invoked using the new keyword when creating an object.

Overloading

Constructors can be overloaded to provide different ways of initializing objects. This is useful when you want to create objects with different initial states. For example, you can create a default constructor that initializes the object with default values and a parameterized constructor that initializes the object with the values passed in.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }
}

Default Constructor

A default constructor is a constructor that takes no parameters. It is provided by default if no other constructors are defined. It initializes the object with default values.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }
}

More on Methods: Actions of a Class

Description

Methods are blocks of code that perform specific tasks. They are declared with a return type, method name, and parameters. They represent behaviors or actions. Methods can be overloaded to provide different ways of performing the same task. This is useful when you want to perform the same task but with different inputs. For example, you can create a method that takes in a string and prints it to the console and another method that takes in an integer and prints it to the console.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }

  // methods
  public void drive() {
    System.out.println("Driving...");
  }

  public void drive(int speed) {
    System.out.println("Driving at " + speed + " mph");
  }
}

Declaration

Methods are declared with a return type, method name, and parameters.

public void drive() {
  System.out.println("Driving...");
}

Return Type

Methods can return a value or be marked as void indicating no return. The return type is specified before the method name.


public void drive() {
  System.out.println("Driving...");
}

public int getSpeed() {
  return speed;
}

Overloading

Methods can be overloaded to provide different ways of performing the same task. This is useful when you want to perform the same task but with different inputs. For example, you can create a method that takes in a string and prints it to the console and another method that takes in an integer and prints it to the console.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }

  // methods
  public void drive() {
    System.out.println("Driving...");
  }

  public void drive(int speed) {
    System.out.println("Driving at " + speed + " mph");
  }
}

Controlling Access: Modifiers

Access Modifiers

Access Modifiers Control the visibility using public, private, protected, or no modifier. The default modifier is package-level.

Description

Access modifiers control the visibility of classes, methods, and variables. They are used to restrict access to certain entities. There are four access modifiers in Java: public, private, protected, and package-level (default).

Private (private)

Restricts visibility to within the class.

Public (public)

Allows open access from all other classes.

Package-Level (no modifier)

Restricts access to classes within the same package.

Protected (protected)

Permits access within the package and to inheriting classes.


Access Modifiers Code Examples

Access modifiers control the visibility of classes, methods, and variables. They are used to restrict access to certain entities. There are four access modifiers in Java: public, private, protected, and package-level (default).

public class Car {
  // instance variables
  private String make;
  private String model;
  private int year;
  private String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }

  // methods
  public void drive() {
    System.out.println("Driving...");
  }

  public void drive(int speed) {
    System.out.println("Driving at " + speed + " mph");
  }
}

Private (private)

Restricts visibility to within the class.

private String make;
private String model;
private int year;
private String color;

Public (public)

Allows open access from all other classes.

public void drive() {
  System.out.println("Driving...");
}

public void drive(int speed) {
  System.out.println("Driving at " + speed + " mph");
}

Package-Level (no modifier)

Restricts access to classes within the same package.

class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }

  // methods
  public void drive() {
    System.out.println("Driving...");
  }

  public void drive(int speed) {
    System.out.println("Driving at " + speed + " mph");
  }
}

Protected (protected)

permitted access within the package and to inheriting classes.

protected void drive() {
  System.out.println("Driving...");
}

protected void drive(int speed) {
  System.out.println("Driving at " + speed + " mph");
}

Inheritance

Inheritance is achieved using the extends keyword. The subclass inherits the properties and behaviors of the superclass.

public class Vehicle {
  // class members
  public static void main(String[] args) {
    // main method
  }

  public void drive() {
    // drive method
    System.out.println("Driving...");
  }
}
// Car inherits from Vehicle
public class Car extends Vehicle {
  // class members

}
Car car = new Car();
car.drive(); // inherited from Vehicle prints "Driving..."

Nested Entities

Nested classes or interfaces can be declared within a class.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
  }

  // nested class
  public class Engine {
    // class members
  }

  // nested interface
  public interface Vehicle {
    // interface members
  }
}

Summary

Classes in Java are the blueprint or prototype for creating objects, encapsulating data and behaviors in a unified structure. Classes are declared with the class keyword, and they can be instantiated to create objects. Classes contain the following components: instance variables, methods, constructors, and nested classes or interfaces.


AP CSA Homework Assignment

Assignment

Instructions

Create a class called Car with the following properties:

  • make (String)
  • model (String)
  • year (int)
  • color (String)
  • doors (int)

Create a default constructor that initializes the object with default values.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;
  int doors;

  // constructors
  public Car() {
    // default constructor
  }
}

Create a parameterized constructor that initializes the object with the values passed in.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;
  int doors;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color, int doors) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
    this.doors = doors;
  }
}

Create a method called drive that takes in an integer representing the speed and prints "Driving at {speed} mph" to the console.

public class Car {
  // instance variables
  String make;
  String model;
  int year;
  String color;
  int doors;

  // constructors
  public Car() {
    // default constructor
  }

  public Car(String make, String model, int year, String color, int doors) {
    // parameterized constructor
    this.make = make;
    this.model = model;
    this.year = year;
    this.color = color;
    this.doors = doors;
  }

  // methods
  public void drive() {
    System.out.println("Driving...");
  }

  public void drive(int speed) {
    System.out.println("Driving at " + speed + " mph");
  }
}

Make a a few new instances of the Car class and call the drive method on them.

Car car1 = new Car("Toyota", "Camry", 2020, "Red", 4);
Car car2 = new Car("Honda", "Accord", 2019, "Blue", 4);
Car car3 = new Car("Ford", "Mustang", 2018, "Black", 2);

car1.drive(60);
car2.drive(70);
car3.drive(80);

Expand on the class as much as you like. You can add more properties, methods, etc.

Read about instance and static variables and methods and try to use them in your class.

References

Previous
Casting and Type Conversion