Creating Classes

Creating a class is the most basic thing you need to know to do on the second Collegeboard FRQ. This is means that you should be able to define a class with the required attributes and methods within a single unit to make the code more organized and modular.

In some AP CSA Exam question you may need to create the entire class, but in others you may be given the class and told to fill it in with methods and variables.

2023 Example FRQ

Attributes:

The Sign class has two private attributes: message and lineWidth. These attributes store the message to be displayed on the sign and the width of each line, respectively.

Constructor:

The class includes a constructor that initializes the message and lineWidth attributes when a Sign object is created. This constructor follows POJO principles by accepting parameters to set the initial state of the object.

Methods:

numberOfLines(): This method calculates the number of lines needed to display the message on the sign based on the line width. It ensures that the entire message is displayed, even if it spans multiple lines. getLines(): This method formats the message into lines separated by semicolons, ensuring that each line respects the specified line width. Main Method: The main method demonstrates the usage of the Sign class by creating instances of Sign objects and printing information about each sign, including the message, number of lines, and formatted lines.

public class Sign {
    // attributes defined
    private String message;
    private int lineWidth;

    public Sign(String message, int lineWidth) { // Constructor using POJO principles
        this.message = message;
        this.lineWidth = lineWidth;
    }

    public int numberOfLines() { // method used to read num of lines
        int lines = message.length() / lineWidth;

        if (message.length() % lineWidth > 0)
            lines++;

        return lines;
    }

    public String getLines() { // method used to get num of lines
        if (message.length() == 0)
            return null;

        String lines = "";
        String messageRemaining = message;

        while (messageRemaining.length() > lineWidth) {
            lines += messageRemaining.substring(0, lineWidth);
            lines += ";";
            messageRemaining = messageRemaining.substring(lineWidth);
        }

        lines += messageRemaining;

        return lines;
    }

    public static void main(String[] args) {
        // Example of using the Sign class without collections
        Sign sign1 = new Sign("Hey guys this is an example", 20); // Create Sign objects
        Sign sign2 = new Sign("of a POJO", 15);

        // Print information for each Sign object
        System.out.println("Message: " + sign1.message);
        System.out.println("Number of Lines: " + sign1.numberOfLines());
        System.out.println("Lines:");
        System.out.println(sign1.getLines());
        System.out.println();

        System.out.println("Message: " + sign2.message);
        System.out.println("Number of Lines: " + sign2.numberOfLines());
        System.out.println("Lines:");
        System.out.println(sign2.getLines());
    }
}

Sign.main(null);
Message: Hey guys this is an example
Number of Lines: 2
Lines:
Hey guys this is an ;example

Message: of a POJO
Number of Lines: 1
Lines:
of a POJO

Tips For Exam

  • You typically want to follow all naming conventions when doing the AP Exam.
  • You can use personalized variables unless otherwise noted.
  • Methods in classes should be specified as instructed by the question.
  • The methods you create can vary in how they complete the specified task, they just need to execute the task correctly.

Implementing Methods

Data Manipulation:

Methods in POJOs can perform various operations on the data they encapsulate. These operations can include calculations, transformations, validations, or any other logic necessary to modify the data according to the requirements of the application.

Behavioral Methods:

POJOs may contain methods that represent behaviors or actions associated with the object. These methods are not necessarily related to data manipulation but instead define the behavior of the object in response to certain actions or events.

Validation:

Methods can enforce data validation rules to ensure that the data stored within the POJO remains valid and consistent. For example, a method can validate whether a certain attribute falls within a specific range or meets certain criteria before allowing it to be modified.

Data Transformation:

Methods can transform the data stored within a POJO into different formats or representations. This transformation might involve converting data types, formatting strings, or applying business rules to the data.

Complex Operations:

POJO methods can encapsulate complex operations that involve multiple steps or computations. By encapsulating such operations within methods, the complexity of the implementation is hidden from the external code, leading to cleaner and more maintainable code.

Interaction with Other Objects:

Methods in POJOs can interact with other objects, either within the same class hierarchy or external to the class. This interaction might involve invoking methods on other objects, passing data between objects, or collaborating with other objects to achieve a certain behavior or functionality.

public class Sign {
    // attributes defined
    private String message; // Attribute to store the message to be displayed on the sign
    private int lineWidth; // Attribute to store the width of each line on the sign

    // Constructor using POJO principles
    public Sign(String message, int lineWidth) {
        this.message = message; // Initialize the message attribute with the provided message
        this.lineWidth = lineWidth; // Initialize the lineWidth attribute with the provided lineWidth
    }

    // Method to calculate the number of lines needed to display the message on the sign
    public int numberOfLines() {
        int lines = message.length() / lineWidth; // Calculate the number of full lines
        if (message.length() % lineWidth > 0) // Check if there are remaining characters
            lines++; // Increment the number of lines if there are remaining characters
        return lines; // Return the total number of lines
    }

    // Method to format the message into lines separated by semicolons
    public String getLines() {
        if (message.length() == 0) // Check if the message is empty
            return null; // If the message is empty, return null

        String lines = ""; // Initialize a string to store the formatted lines
        String messageRemaining = message; // Initialize a string to store the remaining message

        // Loop until there is no message remaining
        while (messageRemaining.length() > lineWidth) {
            lines += messageRemaining.substring(0, lineWidth); // Add a line of width lineWidth to the lines string
            lines += ";"; // Add a semicolon to separate lines
            messageRemaining = messageRemaining.substring(lineWidth); // Remove the processed characters from the message
        }

        lines += messageRemaining; // Add the remaining message as the last line
        return lines; // Return the formatted lines
    }

    public static void main(String[] args) {
        // Example of using the Sign class without collections
        Sign sign1 = new Sign("Hey guys this is an example", 20); // Create Sign objects
        Sign sign2 = new Sign("of a POJO", 15);

        // Print information for each Sign object
        System.out.println("Message: " + sign1.message); // Print the message of sign1
        System.out.println("Number of Lines: " + sign1.numberOfLines()); // Print the number of lines for sign1
        System.out.println("Lines:");
        System.out.println(sign1.getLines()); // Print the formatted lines for sign1
        System.out.println();

        System.out.println("Message: " + sign2.message); // Print the message of sign2
        System.out.println("Number of Lines: " + sign2.numberOfLines()); // Print the number of lines for sign2
        System.out.println("Lines:");
        System.out.println(sign2.getLines()); // Print the formatted lines for sign2
    }
}

Sign.main(null);
Message: Hey guys this is an example
Number of Lines: 2
Lines:
Hey guys this is an ;example

Message: of a POJO
Number of Lines: 1
Lines:
of a POJO

Tips for Exam:

  • Make sure that all of your method signatures are correct and that you understand them well. This would include the return type, method name, parameters, and access modifiers.
  • Make sure to follow the naming convention assigned by Collegeboard.
  • Try to make the methods as efficient as possible without using built in methods than may cut out pieces of code.
  • If exceptions need to be tested, make sure you add them.

Inheritance and Polymorphism

Inheritance allows POJOs to inherit attributes and methods from parent classes, allowing for code reuse and efficiency. Polymorphism allows objects of different classes (including subclasses) to be treated uniformly through a common interface, leading to flexibility in the code.

public class Displayable {
    protected String message;
    protected int lineWidth;

    public Displayable(String message, int lineWidth) { // constructor using POJO
        this.message = message;
        this.lineWidth = lineWidth;
    }

    public int numberOfLines() { // method to read num of lines
        int lines = message.length() / lineWidth;
        if (message.length() % lineWidth > 0)
            lines++;
        return lines;
    }

    public String getLines() { // method to get the lines
        if (message.length() == 0)
            return null;

        String lines = "";
        String messageRemaining = message;

        while (messageRemaining.length() > lineWidth) {
            lines += messageRemaining.substring(0, lineWidth);
            lines += ";";
            messageRemaining = messageRemaining.substring(lineWidth);
        }

        lines += messageRemaining;
        return lines;
    }
}

// Subclass Sign inherits from Displayable
public class Sign extends Displayable {
    public Sign(String message, int lineWidth) { // constructor for creating the sigh with the message
        super(message, lineWidth);
    }
}

// Another subclass AdvertisementSign also inherits from Displayable
public class AdvertisementSign extends Displayable {
    public AdvertisementSign(String message, int lineWidth) { // another constructor
        super(message, lineWidth);
    }

    // Additional method specific to AdvertisementSign
    public void displayAdvertisement() {
        System.out.println("Advertisement: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        // Create objects of Sign and AdvertisementSign
        Displayable sign1 = new Sign("Hey guys this is an example", 20);
        Displayable adSign = new AdvertisementSign("50% off all items", 25);

        // Print information for each Displayable object
        System.out.println("Message: " + sign1.message);
        System.out.println("Number of Lines: " + sign1.numberOfLines());
        System.out.println("Lines:");
        System.out.println(sign1.getLines());
        System.out.println();

        System.out.println("Message: " + adSign.message);
        System.out.println("Number of Lines: " + adSign.numberOfLines());
        System.out.println("Lines:");
        System.out.println(adSign.getLines());

        // Demonstrate polymorphism by calling the displayAdvertisement() method
        if (adSign instanceof AdvertisementSign) {
            ((AdvertisementSign) adSign).displayAdvertisement(); // AdvertisementSign class is able to display messages differently
        }
    }
}

Main.main(null);
Message: Hey guys this is an example
Number of Lines: 2
Lines:
Hey guys this is an ;example

Message: 50% off all items
Number of Lines: 1
Lines:
50% off all items
Advertisement: 50% off all items

Tips for Exam:

  • Make sure to know how these work. Although you may not be asked to write everything from scratch, some parts may ask you to implement these ideas.
  • Know the scopes of your variables. Pay attention to access of different variables as you move across classes.

Working with Collections

  • During the AP CSA Exam, you might come across a question asking for you to use a type of collection or objects like a ArrayList or Strings and manage a group of POJOs

  • POJOs also help to reduce the number of times that something is instantiated, allowing for a more organized and possibly simpler code

  • POJO are really effective especially when it comes to object oriented programming

// Example is from the AP CSA FRQ 2023, Question 2 but modified a little 

import java.util.ArrayList;

public class Sign {
    private String message;
    private int lineWidth;

    public Sign(String message, int lineWidth) { // Constructors using POJOs
        this.message = message;
        this.lineWidth = lineWidth;
    }

    public int numberOfLines() {
        int lines = message.length() / lineWidth;

        if (message.length() % lineWidth > 0)
            lines++;

        return lines;
    }

    public String getLines() {
        if (message.length() == 0)
            return null;

        String lines = "";
        String messageRemaining = message;

        while (messageRemaining.length() > lineWidth) {
            lines += messageRemaining.substring(0, lineWidth);
            lines += ";";
            messageRemaining = messageRemaining.substring(lineWidth);
        }

        lines += messageRemaining;

        return lines;
    }

    public static void main(String[] args) { // Example of managing a collection of Sign objects
        ArrayList<Sign> signs = new ArrayList<>();

        signs.add(new Sign("Hey guys this is an example", 20)); // Create and add Sign objects to the collection
        signs.add(new Sign("of a POJO in a collection", 15));

        for (Sign sign : signs) { // Print information for each Sign object
            System.out.println("Message: " + sign.message);
            System.out.println("Number of Lines: " + sign.numberOfLines());
            System.out.println("Lines:");
            System.out.println(sign.getLines());
            System.out.println();
        }
    }
}
Sign.main(null)
Message: Hey guys this is an example
Number of Lines: 2
Lines:
Hey guys this is an ;example

Message: of a POJO in a collection
Number of Lines: 2
Lines:
of a POJO in a ;collection

One important thing to note:

  • POJOs aren’t always required for the CSA FRQ and sometimes aren’t even in the requirements for the question, however, it is something that you should know and should have as one of you different techniques to approaching code especially when it comes to working code using OOP and also serves a good way to understand/show understanding of Java better and also, the AP Exam always accepts the initialization of variable through POJO and its a good habit to have

Serialization and Deserialization (not really a focus on the AP Exam)

  • Serialization and Deserialization is the conversion of an object into a more storable or transmittable form of data (serialization) and then converting those objects back to a Java Objects

  • Examples would be: JSON and XML

Here is a diagram showing a general idea of how it works:

Serialization and Deserialization Diagram

While not on the AP Exam, they are a very important part of Java programming and a basic understanding can help alot

Encapsulation and Access Control

  • One of the things that the AP Exam commonly makes sure that you know and have during the FRQ section in teh encapsulation and access control

Encapsulation:

  • Encapsulation is one of the 4 main OOP concepts that the AP CSA Exams tests on (the others are inheritance, polymorphism and abstraction)

  • Encapsulation is done through using classes and access modifiers

  • Ways you might be asked to do this or could see this is through defining private fields and providing setters and getters and other public methods to access and modify those fields

  • Encapsulation allows for protection against other parts of the program by preventing them to modify it

Access Control

  • Determines what is visible and what isn’t in a program and protects data integrity

  • The exam might ask questions that will cause you to decide and apply the right access modifiers (private, public) and the MC section might even test your ability to determine which ones are incorrect and why

  • Declaring the right Access Controls can account for 4/10 of the points on the FRQ and so it is very important that you understand what and why each access control is used

Example:

import java.util.ArrayList;

public class Sign {
    private String message; // private variables, encapsulates the 'Sign' object, hiding it from other classes
    private int lineWidth;

    public Sign(String message, int lineWidth) { // Constructors using POJOs
        this.message = message;
        this.lineWidth = lineWidth;
    }

    public int numberOfLines() { // public method that provides controlled access to the private data members
        int lines = message.length() / lineWidth;

        if (message.length() % lineWidth > 0)
            lines++;

        return lines;
    }

    public String getLines() { // public method that provides controlled access to the private data members
        if (message.length() == 0)
            return null;

        String lines = "";
        String messageRemaining = message;

        while (messageRemaining.length() > lineWidth) {
            lines += messageRemaining.substring(0, lineWidth);
            lines += ";";
            messageRemaining = messageRemaining.substring(lineWidth);
        }

        lines += messageRemaining;

        return lines;
    }
}