• Labs icon Lab
  • Core Tech
Labs

Guided: Java SE 21 Developer (Exam 1Z0-830) - Object-oriented Programming

This code lab will teach you how to apply core object-oriented programming principles in Java by building a festival performance application. You'll learn how to implement encapsulation, abstraction, inheritance, and polymorphism through hands-on tasks. By the end of this lab, you'll have practical experience building object-oriented Java applications.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 1h 5m
Published
Clock icon Feb 14, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Welcome to the lab Guided: Java SE 21 Developer (Exam 1Z0-830) - Object-oriented Programming.

    Object-Oriented Programming (OOP) is a programming paradigm that organizes code into objects, which are instances of classes containing both data and behavior. Java, being an object-oriented language, supports OOP's core principles: encapsulation, inheritance, polymorphism, and abstraction.

    Consider this scenario:

    // Without OOP
    String performanceName = "The Coders";
    String performanceType = "music";
    int startTime = 1900;
    int duration = 60;
    int numberOfPerformers = 4;
    
    // With OOP
    MusicPerformance performance = new MusicPerformance(
        "The Coders", 
        new TimeSlot(1900, 60), 
        "Rock", 
        4
    );
    

    The OOP approach provides several advantages:

    • Encapsulation: Data and behavior are bundled together, with access control
    • Inheritance: Common characteristics can be shared through class hierarchies
    • Polymorphism: Different objects can be treated uniformly through common interfaces
    • Abstraction: Complex systems can be simplified by hiding implementation details

    In this lab, you'll work with a Festival Performance Management application that demonstrates these principles:

    • Creating an inheritance hierarchy of performance types
    • Implementing encapsulated data with getters and setters
    • Using polymorphism to handle different performance types uniformly
    • Applying abstraction to define common behaviors ---

    Familiarizing with the Program Structure

    The application includes the following classes in the src/main/java directory:

    • com.pluralsight.festival.Performance: An abstract base class defining common structure for all performance types
    • com.pluralsight.festivalMusicPerformance, com.pluralsight.festival.ComedyPerformance, and com.pluralsight.festival.DancePerformance: Concrete classes extending Performance
    • com.pluralsight.festival.TimeSlot: A utility class for managing performance scheduling
    • com.pluralsight.festival.Stage: A class managing a collection of performances
    • com.pluralsight.festival.Main: The application's entry point demonstrating the usage of all components

    The TimeSlot class is fully implemented. Other classes are partially implemented with TODO comments indicating where you'll need to add or modify code.

    You can compile and run the application using the Run button located at the bottom-right corner of the Terminal. However, the application will not compile initially, but this issue will be resolved after completing the first task.

    Begin by examining the code to understand the program's structure. Once you're ready, proceed with the coding tasks. If you need help, you can find solution files in the solution directory, organized by steps (e.g., step2, step3, etc.). Each solution file follows the naming convention [filename]-[step]-[task].java (e.g., Performance-2-1.java in step2).

  2. Challenge

    Implementing Encapsulation and Abstraction

    Encapsulation

    Encapsulation bundles data and the methods that operate on that data within a single unit (class), controlling access through access modifiers:

    public class BankAccount {
      // Data is private
      private double balance;
      
      // Public access getter method
      public double getBalance() {
        return balance;
      }
      
      // Public access method
      public void deposit(double amount) {
        if (amount > 0) {
          balance += amount;
        }
      }
    }
    

    These are the access modifiers that apply to fields and methods:

    • private: Only accessible within the class
    • protected: Accessible within the package and by subclasses
    • public: Accessible from anywhere
    • Default (no modifier): Accessible only within the package

    Also, inside getter or setter methods, you can perform validations, conversions, or other operations before retrieving or modifying the data.

    In the next task, you'll apply these principles to implement encapsulation. ---

    Abstraction

    Abstraction defines a contract for what an object can do without specifying how it's done. In Java, one way to achieve abstraction is through abstract classes and methods.

    Here's an example of an abstract class with an abstract and a concrete method:

    public abstract class Shape {
      public abstract double calculateArea(); // Abstract method
      
      public void display() {  // Concrete method
        System.out.println("Area: " + calculateArea());
      }
    }
    

    If a class contains at least one abstract method, the class should be marked as abstract.

    Abstract methods:

    • Must be implemented by concrete subclasses
    • Cannot have a body in the abstract class
    • Force subclasses to provide specific implementations

    The benefits of using abstract classes include:

    • Define a common interface for related classes
    • Share code through concrete methods
    • Ensure consistent behavior across implementations
    • Prevent instantiation of incomplete classes

    In the next task, you'll apply these principles to implement abstraction.

  3. Challenge

    Building the Inheritance Hierarchy

    When creating class hierarchies in Java, subclasses inherit fields and methods from their parent class using the extends keyword:

    public class Animal {
      private String name;
      
      public Animal(String name) {
        this.name = name;
      }
    }
    
    public class Dog extends Animal {
      // ...
    }
    

    This relationship creates an is-a relationship between classes.

    Subclasses must call their parent's constructor using super(). This call:

    • Must be the first statement in the constructor
    • Ensures proper initialization of inherited fields
    • Can pass arguments to match the parent's constructor parameters
    public class Dog extends Animal {
      private String breed;
      
      public Dog(String name, String breed) {
        super(name);  // Call parent constructor first
        this.breed = breed;
      }
    }
    

    Notice that in the above example, breed is not passed to super() because this is a field that only exists in the Dog class.

    Depending on its access modifiers, fields and methods can be inherited from the parent class. However, methods can be overridden (redefined) to provide custom behavior for the subclasses.

    When overriding methods from a parent class:

    • Use the @Override annotation to catch errors
    • Match the method signature exactly
    • Provide a new implementation specific to the subclass
    • Cannot reduce the visibility of the inherited method
    public class Vehicle {
      public String getSpecs() {
        return "Generic vehicle";
      }
    }
    
    public class Car extends Vehicle {
      @Override
      public String getSpecs() {
        return "Four-wheeled vehicle";
      }
    }
    

    Remember:

    • Abstract methods must be implemented by concrete subclasses
    • The @Override annotation helps prevent accidental method overloading
    • Each subclass can provide its own specialized behavior while maintaining the parent's contract

    In the upcoming tasks, you'll apply these concepts to create specialized performance types with their own unique descriptions:

    • A comedy performance adds comedian name and adult-only status to track stand-up comedy shows.
    • A dance performance adds number of dancers and dance style to represent choreographed shows.
    • A music performance adds genre and number of performers to represent band or solo performances.
  4. Challenge

    Implementing Polymorphic Behavior

    Polymorphism allows you to treat objects of different types through a common interface. This feature enables you to write more flexible and maintainable code.

    For example, when you store objects of different types in a collection or variable of their common supertype, Java automatically calls the correct implementation of overridden methods:

    abstract class Animal {
      public abstract String makeSound();
    }
    
    class Dog extends Animal {
      @Override
      public String makeSound() {
        return "Woof!";
      }
    }
    
    class Cat extends Animal {
      @Override
      public String makeSound() {
        return "Meow!";
      }
    }
    
    // Using polymorphism
    List<Animal> animals = new ArrayList<>();
    animals.add(new Dog());
    animals.add(new Cat());
    
    // Each animal uses its own implementation
    for (Animal animal : animals) {
      System.out.println(animal.makeSound());
    }
    

    When managing collections of related objects:

    • Store objects using the most general type possible
    • Process objects uniformly through their common interface
    • Let each object's specific implementation handle the details

    In the next tasks, you'll apply these concepts to manage different types of performances through a common interface, allowing each type to provide its specific behavior while being handled uniformly.

  5. Challenge

    Instantiating Objects

    When creating objects in Java, you can store them in variables of their own type or any of their parent types. This flexibility is key to polymorphic behavior.

    Creating objects involves:

    • Using the new keyword
    • Calling a constructor with appropriate parameters
    • Storing the reference in a variable
    // Direct type reference
    Vehicle sedan = new Car("Model S", 4);
    
    // Parent type reference (polymorphic)
    Vehicle truck = new Truck("F-150", 6);
    

    You can assign objects to variables of:

    • The exact class type
    • Any parent class type
    • Any interface the class implements
    interface Drawable { }
    class Shape implements Drawable { }
    class Circle extends Shape { }
    
    // All these are valid
    Circle circle = new Circle();
    Shape shape = new Circle();
    Drawable drawable = new Circle();
    

    When instantiating objects:

    • Parameters must match one of the class's constructors
    • Arguments must be in the correct order
    • Arguments must be of compatible types
    class Book {
      public Book(String title, String author, int pages) {
        // ... Validations and initialization
      }
    }
    
    // Creating with valid parameters
    Book book = new Book("Java Programming", "John Smith", 400);
    

    In the next tasks, you'll apply these concepts to create different types of performances while maintaining type safety and proper initialization.

  6. Challenge

    Conclusion

    Congratulations on successfully completing this Code Lab!

    To compile and run the application, you can either click the Run button in the bottom-right corner of the screen or use the Terminal with the following commands:

    1. Compile and package the application:

      mvn clean package
      
    2. Execute the application:

      java -cp target/festival-manager-1.0-SNAPSHOT.jar com.pluralsight.festival.Main
      

    The program will output the scheduled performances.

    You can try adding more performances of different types or modify the existing ones in the Main class. In particular, see what happens when you schedule overlapping performances. ---

    Extending the Program

    Here are some ideas to further enhance your skills and extend the application's capabilities:

    1. Create a TheatrePerformance class with props list and cast size

    2. Add a composite pattern to group performances into festivals or themed shows

    3. Implement the state pattern for performance lifecycle (Setup, Ready, Running, Completed)

    These extensions emphasize different OOP principles and design patterns while adding practical functionality to the festival management system. ---

    Related Courses in Pluralsight's Library

    If you'd like to continue building your Java skills or explore related topics, check out these courses available on Pluralsight:

    These courses cover a wide range of Java programming topics. Explore them to further your learning journey in Java!

Esteban Herrera has more than twelve years of experience in the software development industry. Having worked in many roles and projects, he has found his passion in programming with Java and JavaScript. Nowadays, he spends all his time learning new things, writing articles, teaching programming, and enjoying his kids.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.