Class Structure: Member Variables and Methods

Parent Component: Langauge Structures

We've been working with classes since day 1 in Java! This module's goal is to make our understanding of class structure more robust and systematic. Thankfully, classes, while entirely essential in Java, all follow a similar structure: they contain member variables and then a bunch of methods. That's it! Our next component (set of modules) will explore how we can use a well-formed class to create Objects in Java.

Jump to a section

Learning Objectives
Module "hamburger" guide
Core Concepts
Resources and reference documents
Module Preparation Exercises
Exercise 1:
Exercise 2:
Mini Project:
Extension Exercises

Module Learning Objectives


Describe in English the core components of any Java class: Member variables and methods


Create member variables of appropriate types and justify their placement in Class scope rather than method scop


Create a set of well-designed methods that each accomplish one task and work together to provide a useful set of tools to the class


Refactor (edit) an existing class by placing variables in the appropriate scopes and limiting methods to working on only one task


Resources and Prep-Work

Activities and readings to do prior to our starting the module in class:

Review the following resources related to class structure:

  1. Oracle Online tutorial on class structure. Note that this section is part of a larger section on object-oriented programming, which we haven't covered. Unless you want to study ahead, the sections before and after this one on classes would be extra reading.
  2. Oracle's book: Java:A beginner's Guide -- Chapter 4 starts with an introduction on Class structure and proceeds into methods, which we learned about prior to this lession.


Warm-up Exercise: Calling Methods in main()

Get your head back in JavaLand by calling methods in main() that already exist in the body of the class.

  1. Create a new class called MethodPractice in a sensible package.
  2. Delete the default code the IDE placed in your new class and instead copy and paste the guts of the MethodPractice class in our class github repository.
  3. Read all the code on your screen. Identify the methods and their declarations. Consider what input parameters they require and what they return.
  4. Complete TASKS 1-3 that are described in comments in this code
  5. If you're done with 1-3, try task 4.

A completed class with the method calls in main() is found here


Module Core Concepts

Classes are the building block of all Java programs--the "bricks" of our Java castles. Classes are made up of only two components: member variables (stuff the class "knows") and methods (stuff the class "does"). They get stacked on top of one another.

The essential components in a Java class

Unlike a run-of-the-mill local variable, member variables are declared outside any method and thus are in "shared" class space and any method can acccess them. The diagram below shows how numberOfConversionsCompleted is a member variable that both conversion methods can access, which they do by incrementing the count by 1 each time they are called. yaks, though, is a local variable to convertDucksToYaks() method and cannot be accessed by any code in convertYardsToMiles().

Class member variables have class scope and can be accesed by any method in the class.

When we plan a class, we should declare member variables for values that relate to what the whole class does, such as convert various quantities. If a value is only needed to do a task that a single method carries out, palce the variable in that local method scope.

Classes in Code

If we take a stripped down version of a Converter class and place it next to our evolving diagram of a class, we can see the structure in the code easily:

A covnerter class in Java side-by-side with a class structure diagram.

Remember back to our CarFob class which had an unlock() and configure() method? We can model that class the same way and see its structure of member variables and methods. We chose to make braodFreq, vehicleID, and doorsLocked all class variables since each method might need to access these values to do their work. The rest of the variables, such as a user-entered value, remain in the local method scope.

A model of a car fob called CarFob is a class that shows the relationship between member and local variables.


Exercise 1: Creating a well-formed Kennywood Ride Tracker Class

Exercise type: In-class code-a-long with Eric

Our goal is to create a class that models folks riding thrill and theme rides at Kennywood. We want the class to contain member variables that track the total number of riders across all rides, so park planners can make staffing and resource decisions. The output can look like this: notice that the Rider Stats track three metrics, each one corresponding to a member variable.

Sample program output for kennywood class.
  1. STUDY steps 2-5 with a partner and a single sheet of paper. NO CODE YET! Create a class diagram like the ones in the images above of the member variables, their names, and the methods, and their calls, in your diagram. We'll use this to code but we want to THINK and PLAN first.
  2. Create a new package called ls3_classStructure. Inside the package, create a class called KennywoodRideTracker. Create a main(String[] arts) method.
  3. Create our member variables that store information that all the methods in the class need to have access to:
    • An integer called totalRiders that is private adnd static, initalized to zero. This member tracks the total riders that have ridden on any ride in the class.
    • an integer called totalFailedRideAttempts which is private and static and initialized to zero. This will track the number of riders who tried to board a ride but were too short to pass.
    • an integer called totalSickRiders which is private and static and initialized to zero. This will track the number of riders who get sick on the ride. We'll use a random number generator to pick riders to cast a sick spell on.
    • Two final class members to store the minimum height for riders on the thrill rides and the theme rides. You can name these! These should be declared final static and int. Their names should be in all capitals to signal they are constants. Assign a value in inches to each constant; make the thrill ride minimum higher than the theme ride minimum.
  4. Create two ride simulation methods. The first should be named rideBlackWidow. The second method should be called rideMerryGoRound. Both should accept two parameters:
    • An integer called riders
    • An integer called avgHeight
    Both methods should have a return-type of void and be delcared public and static
  5. Create a fourth method (main() plus the two rides) called printRideStats() that accepts no parameters and doesn't reutrn any value. We'll use this method to keep our main() method clear for testing the individual methods. We want to be able to call printRideStats() and see all our member variables' values displayed! This is separation of concerns: this method prints stats. main() tests methods.

  6. Program the logic inside our ride-simulator methods. We want to pass into each ride a number of riders and their average height. (We'll imagine that all the riders get judged on their average height only.) That sounds like a condition for riding, that can become an if()-controlled block. We want to add our riders and turned away riders to their respective member variables. We also want to generate a random number of riders who get sick and add that to our third member variable.

    Use this method flow diagram to try programming the guts of rideBlackWidow:
    The flow of execution system diagram for a java method's guts Your call to Random.nextInt(int bound) will involve three lines of code: the imprt statment for java.util.Random, a line that creates a Random object, and a line that calls a method on that Random object:

    You can do the import statement-- add the line import java.util.Random right before you declare your class.

    The Random object creation and call to its method are shown here:

    The flow of execution system diagram for a java method's guts
    Read instructions 3x and try writing code before peeking!
  7. Copy and adapt your rideBlackWidow() method's guts you just wrote into the abodmen of the rideMerryGoRound() method. You should now have two methods ready to accept riders!

    Read instructions 3x and try writing code before peeking!
  8. Write the code for the printRiderStats(). This is a simple method with only System.out.println() calls which each display one of our three member variables. Check the sample output at the start of this lesson to generate the code.

    Read instructions 3x and try writing code before peeking!
  9. We're ready to test our methods and member variables in main()! Our code in main() is very simple. We alternate calling printRiderStats() to show the status of our member variables and calling individual ride's methods, passing in a rider count and height of your choosing. Flesh out your main() method with at least 5 calls to rides with riders of various heights, some of which do not pass the minimum threshold. Test your code to make sure the member variables are correctly incremented.

    Read instructions 3x and try writing code before peeking!
  10. Grab your class diagram and check to see if the diagram and your new code are consistent. Discuss with your partner what the differences are between your plan and how we carried the plan out. Reflect on how you can create more accurate class digrams, please.


Exercise 2: Building out our unit Converter classes

Exercise type: Teamwork task and Code Sharing

We all have our Converter classes which we used to simulate method calls with slips of paper. We'll explore class structure by adding methods to our Convter classes that other members of CIT111 wrote and posted.

If we know the method's contract: it's input parameters and reutrn values, we can easily use methods other then the ones we write to accomplish programming tasks. We need to call the method and provide values to the input parameters. If a return type exists, we must prepare to handle that value.

Just like the example in the diagrams above, we'll create a member variable called numberConversionsProcessed that we'll increment each time we call a conversion method.

  1. Open your Converter class from our previous module on methods.
  2. Run your code to check that the class is behaving correctly. You should have a method call in main() down to your coversion method, and print out the return type to the console. Some of you have a user-input system wired up, that's fine, too.
  3. Build in a class member variable to track the total number of conversions processed. Call this variable totalConversionsProcessed and declare it with an initial value of zero. (Remember where member variables go.)
  4. We now need to adjust our conversion method's code to increment this member variable: totalConversionsProcessed just like we did with the Kennywood Park Rider class. In this case, however, each method call only increments totalConersionsProcessed by one, not a passed in number.
  5. Build a println() statement in main() that displays the value of totalConversiosnProcessed before and after the call to your conversion method.
  6. Prepare to share your converter method by creating a special kind of comment called a JavaDoc comment before your method. Position your cursor on the line directly before your method declaration. Type "/**" and then press enter. A special comment block should appear in Netbeans that lists the input parameter names and a line for the return value. Start by writing a line of text under the line that starts with "/**" that lists what the method does. Then note what your method expects for input parameters. Note what the return value means. Here's a sample JavaDoc Comment:

    JavaDoc comment example for a methhod
  7. With your JavaDoc comment complete, you are ready to share your method in our class "method repository" which is a google doc with a table of contents. Open the google doc here. Navigate to a blank page at the bottom of the file. Press control + 1 to toggle into header mode. You should see "heading 1" appear in the upper right of the format bar.
  8. Type your method's purpose and your name in the heading one. Press enter to return to normal paragraph text. Then paste in your conversion method along with its JavaDoc comments. Here's a sample:

    sample upload of a method to our shared google doc repository
  9. Now that your method is posted to share with the world, find two additionaly methods from the repository to add to your class. Copy and paste the entire method and JavaDoc comment from the google doc into your class. Read the method carefully and work on making sure the member variable to tally total conversions processed is spelled the same way in your class and in the new methods you are inserting.
  10. Now implement calls to each of your new methods and be sure to print out the value of totalConversionsProcessed after each call to show that your member variable is "working".
  11. Try calling the same method a few times with different values to test the functionality.

Extend your converter class with a switch statement

We can create a menu interface in our Converter class such that the user can select the conversion method they want to use and our program will register their choice and call the appropriate method using a switch statement.

We want the interface to operate something like this:

switch statement in java produces a nice output
  1. Read on Oracle's site about Switch statements. They are basically chained if-controlled blocks that check for equality between the integer in () next to the keyword switch.
  2. In order for switch to work in this system, we'll need to refactor each method so that it takes in double values and returns only double values. This way we can ask the user to enter a value to be converted and that will work for all the three conversion methods we have in our Converter classs
  3. Now implement the user interface by creating a Scanner object. (Import java.util.Scanner). Write println() statements that provide the user a menu. Then ask for an int with the scanner.
  4. Then ask the user for the value to convert. Store this in a double.
  5. Now build your switch statement that tests the value of the user's choice integer with case values: 1, 2, 3, etc. If the user enters 2 for converting yardsToMiles, say, we want the switch statement to only call convertYardsToMiles with the user's input.
  6. Don't forget to use a break; statement in each switch clause so the rest of the cases don't all get called after the selected one.
  7. Print the value of numberConversionsProcessed after the switch statement
  8. EXTRA: Create a while()-controlled block that will allow the user to convert values over and over again, and we can see the counter incremented as this occurs.
Read instructions 3x and try writing code before peeking!


Extension activities

Exercise type: On-your-own explorations

Try these adjustments and/or embellishments of our classes we've worked on in this module

  1. Create a system in our new Converter class that monitors the average of all the values the user has asked to convert. You'll need to do some thinking about how to create a new average value and store it to a member variable after each submission of a value to convert. Take your time and study how to add an average to an average and get a reasonable response.
  2. Add a ticket price for youth and adults in our KennywoodRideTRacker class. This means two more member variables. Add a third new member variable called totalRevenue that tracks ticket sales overall. Now, if somebody rides a theme ride, like the Merry-go-round, we want to increment the number of "youth" and calcualte a total ticket revenue. If a rider rides the thrill ride, consider those riders adults, a multiply the number of riders times the ticket price for adults, and add that value to your totalRevenue member variable. Do the same for youth. Print out the revenue in printRiderStats() method.