Skip to content

Lab 7: Enumerated Types

Instructions

Answer the following questions one at a time. After answering each question, check your answer before proceeding to the next question.

Save the following file in your lib/ folder:

Save the following files in src/labs/lab07:

Acknowledgment

This lab was written by Prof. David Bernstein. The original version is here.

Background Material

For this lab, you are going to be working with Air Quality Indexes as they are defined by the U.S. Environmental Protection Agency (EPA). You don't need to know much about them, other than the information that is summarized in the following table.

Category Min Max Description Color
(R, G, B)
GOOD 0 50 Good Green
(0, 228, 0)
MODERATE 51 100 Moderate Yellow
(255, 255, 0)
SENSITIVE 101 150 Unhealthy for Sensitive Groups Orange
(255, 126, 0)
UNHEALTHY 151 200 Unhealthy Red
(255, 0, 0)
VERY_UNHEALTHY 201 300 Very Unhealthy Purple
(153, 0, 76)
HAZARDOUS 301 500 Hazardous Maroon
(126, 0, 35)

Motivation and Review

To motivate the need for enumerated types, in this part of the lab you are going to construct a small application that makes use of the Announcement class to display air quality information.

  1. Briefly review ShowAQI.java.

  2. Based on your review of ShowAQI, what is required to execute it "properly"?

    Answer

    It needs to be given a command-line parameter.

  3. Execute ShowAQI using what you know is required to execute it "properly". What happened?

    Answer

    A window like the following appeared.

    Screenshot of ShowAQI

    How to run ShowAQI with a command-line parameter?

    Step 1: Open src/labs/lab07/ShowAQI.java in VS Code and press F5 to run the program. This will launch a Terminal window. In the Terminal output, you will see two sections: The command executed to run ShowAQI, and the program output, which displays: Usage: java ShowAQI aqi.

    Step 2: Press the Up arrow key on your keyboard to recall the previous command used to run ShowAQI. Then, add a space followed by the desired command-line argument. Finally, press Enter to execute the command.

    An easier way to run ShowAQI without pressing F5

    Alternatively, you can type the command yourself (without any extra junk from VS Code):

    OS Command
    Linux / macOS java -cp "bin:lib/*" labs.lab07.ShowAQI 50
    Windows java -cp "bin;lib\*" labs.lab07.ShowAQI 50

    Explanation:

    • java is the command for running a Java application
    • -cp stands for classpath, which tells Java where to find .class and .jar files
    • labs.lab07.ShowAQI is the fully-qualified name (including package) of the main class to run
    • 50 (or any other number) is the command-line argument passed to the args parameter of main()
  4. Review the source code for ShowAQI. Why did the window have the color and text that it did?

    Answer

    Because the findColor() method always returns yellow, and the findDescription() method always returns "Moderate".

  5. Why are the findColor() and findDescription() methods static?

    Answer

    Because they are going to be called from a static context, specifically the main() method. Since main() is static (and will be called without reference to a ShowAQI object), every method/attribute in the ShowAQI class that main() calls/uses must also be static.

  6. Why don't they need to be called as ShowAQI.findColor() and ShowAQI.findDescription()?

    Answer

    Because they, and main(), are all in the ShowAQI class.

  7. Modify the findColor() method so that it returns the appropriate Color object. To save time, only consider the first three categories, and treat SENSITIVE as the default. (Don't be fancy – just use nested if statements or a switch statement and hard-code the ranges.)

    Answer
    private static Color findColor(int aqi)
    {
        Color    result;
    
        if ((aqi >= 0) && (aqi <= 50))
        {
            result = new Color(0, 228, 0);
        }
        else if ((aqi >= 51) && (aqi <= 100))
        {
            result = new Color(255, 255, 0);
        }
        else
        {
            result = new Color(255, 126, 0);
        }
    
        return result;
    }
    
  8. Modify the findDescription() method so that it returns the appropriate String object. Again, to save time, only consider the first three categories, treat SENSITIVE as the default, and don't be fancy.

    Answer
    private static String findDescription(int aqi)
    {
        String    result;
    
        if ((aqi >= 0) && (aqi <= 50))
        {
            result = "Good";
        }
        else if ((aqi >= 51) && (aqi <= 100))
        {
            result = "Moderate";
        }
        else
        {
            result = "Unhealthy for Sensitive Groups";
        }
    
        return result;
    }
    
  9. If you were a system tester (not a unit tester) who had been tasked with building a complete system test suite, what information would you use to identify important test cases?

    Answer

    The table that was included in the background material.

  10. Would this be black-box or white-box testing?

    Answer

    It would be black-box testing because the tester would not have access to the source code.

  11. Conduct a few system tests to see if your application is working. Don't be comprehensive.

  12. The design of the ShowAQI application is not very good. For one thing, the ShowAQI class is not cohesive (i.e., it does too many different kinds of things). For another, the implementations of findColor() and findDescription() contain duplicate code. How can these two problems be solved?

    Answer

    The second problem can be solved by creating a class named AirQuality that contains both a Color and a String (as well as the int AQI). That way, one method could "find" and return both at the same time.

    The first problem can be solved by moving the "find" functionality to the AirQuality class. This would make the ShowAQI class much more cohesive.

  13. In the "real world", how many different AirQuality objects are there?

    Answer

    Six, one for each category in the table above.

  14. Given your answer to the previous question, should AirQuality be a class or an enum? In other words, do we need an intensive definition or an extensive definition of the set of AirQuality objects?

    Answer

    Since there are only six possible AirQuality objects, the right thing to do is just list them all (i.e., use an extensive definition). In other words, AirQuality should be an enum.

An Initial Encapsulation

This part of the lab will get you started designing and implementing enumerated types.

  1. Review the AirQuality enum. How many different AirQuality objects are there?

    Answer

    As expected, six.

  2. Why is the constructor private?

    Answer

    So that "nobody else" can create an AirQuality object (since, after all, there can only be six).

  3. How many different attributes does each AirQuality object have?

    Answer

    Four: a description, a color, a minimum AQI value, and a maximum AQI value.

  4. Add accessors for the color and description.

    Answer
    /**
    * Get the color associated with this AirQuality object.
    *
    * @return  The Color
    */
    public Color getColor()
    {
        return color;
    }
    
    /**
    * Get the description associated with this AirQuality object.
    *
    * @return  The description
    */
    public String getDescription()
    {
        return description;
    }
    
  5. Add a boolean contains(int aqi) method to AirQuality that returns true if aqi is in the interval [min, max] and false otherwise. Do not use an if statement, a switch statement, ternary operator, or local variables!

    Answer
    /**
    * Determine whether a given AQI is within the range of this AirQuality object.
    *
    * @return   true if the AQI is in [min, max]; false otherwise
    */
    public boolean contains(int aqi)
    {
        return ((aqi >= min) && (aqi <= max));
    }
    
  6. Replace the Color findColor(int aqi) and String findDescription(int aqi) methods in the ShowAQI class with a AirQuality findAirQuality(int aqi) method. Again, limit your implementation to the first three categories. However, this time, don't use hard-coded ranges. Instead, use the contains() method in the AirQuality enum.

    Answer
    /**
    * Find the AirQuality object associated with a particular
    * air quality index (AQI).
    *
    * @param   aqi   The air quality index
    * @return        The associated AirQuality
    */
    private static AirQuality findAirQuality(int aqi)
    {
        AirQuality result;
    
        if (AirQuality.GOOD.contains(aqi))
        {
            result = AirQuality.GOOD;
        }
        else if (AirQuality.MODERATE.contains(aqi))
        {
            result = AirQuality.MODERATE;
        }
        else
        {
            result = AirQuality.SENSITIVE;
        }
    
        return result;
    }
    
  7. Modify the main() method of the ShowAQI class so that it uses the findAirQuality() method.

    Answer
    /**
    * The entry-point of the application.
    *
    * @param args  The command-line arguments
    */
    public static void main(String[] args)
    {
        AirQuality quality;
        Announcement announcement;
        int          aqi;
    
        if ((args == null) || (args.length < 1))
        {
            System.out.println("\nUsage: java ShowAQI aqi\n");
        }
        else
        {
            aqi = Integer.parseInt(args[0]);
            quality = findAirQuality(aqi);
    
            if (quality == null) {
                System.out.println("\nInvalid AQI. Please try again.\n");
            } else {
                announcement = new Announcement(quality.getDescription(),
                        quality.getColor());
                announcement.setVisible(true);
            }
        }
    }
    
  8. Test the modified ShowAQI.

  9. Is ShowAQI cohesive?

    Answer

    Not yet.

An Improved Encapsulation

This part of the lab will help you understand why and how to build functionality into enumerated types.

  1. Move the findAirQuality() method from the ShowAQI class to the AirQuality enum. (Note: You will have to change the visibility to public.)

  2. Why is the findAirQuality() method static?

    Answer

    Because it is going to be used to find an AirQuality object. If it weren't static, we would need an AirQuality object before we could call it.

  3. Modify the ShowAQI class so that it uses the findAirQuality() method in the AirQuality class.

    Answer
    quality = AirQuality.findAirQuality(aqi);
    
  4. Why do you now need to include the class name in the call to the method?

    Answer

    Because findAirQuality() is in the AirQuality class and this statement is in the ShowAQI class.

  5. Test the modified ShowAQI.

  6. Is the ShowAQI class cohesive?

    Answer

    Yes. It now does one thing – it shows air quality information.

  7. Is the findAirQuality() method in the AirQuality class complete?

    Answer

    No, it only works for three of the six AirQuality objects.

  8. Given that there are only six different AirQuality objects, how long would it take to add the other three cases?

    Answer

    A minute or two.

  9. Suppose there were 100 different AirQuality objects, how long would it take to add the other 97 cases?

    Answer

    It would take some time, and it would be annoying.

  10. Suppose an AirQuality need to be added to the enum three years from now. How likely is it that you will remember to also modify the findAirQuality() method?

    Answer

    Very unlikely!

  11. Use the values() method and a traditional for loop to fully-implement the findAirQuality() method. (Return null if the if the aqi is out of bounds.)

    Answer
    /**
    * Find the AirQuality object associated with a particular
    * air quality index (AQI).
    *
    * @param   aqi   The air quality index
    * @return        The associated AirQuality
    */
    public static AirQuality findAirQuality(int aqi)
    {
        AirQuality[]   all;
        all = AirQuality.values();
        for (int i=0; i<all.length; i++)
        {
            if (all[i].contains(aqi))
            {
                return all[i];
            }
        }
        return null;
    }
    
  12. Test the modified ShowAQI.

Submission

  1. Submit only AirQuality.java and ShowAQI.java to Gradescope.
  2. Answer the questions in Canvas for your section's Lab 7 assignment based on this lab.