Skip to content

Lab 3: Writing a Class

In this lab, you will implement a Car class that represents a car. You will learn about non-static attributes and methods. And you will gain experience creating and using objects.

Learning Objectives

After completing this lab, you should be able to:

  • Interpret a UML class diagram and stub out the corresponding code.
  • Implement constructors, accessors, mutators, equals, and toString.
  • Write a test program that calls non-static methods of another class.
  • Learn how to effectively use AI tools to assist your learning.

AI Assistance ✨

For this lab, do not use AI tools to generate code solutions. This is part of the learning process, and we don't want you to miss out!

There will be portions of this lab that will have examples of how to effectively use AI tools to help boost your learning.

We recommend using Microsoft Copilot Chat (free for all JMU students). You are free to use other AI tools if you prefer.

Step 1. Getting Started

Do the following steps in VS Code:

  1. Create a lab03 folder under your src/labs folder.
  2. Add two new files: Car.java and Main.java.
  3. Write the package and public class statements.
  4. Write a Javadoc comment with your name and date.

When finished, your Car.java and Main.java should look like this:

VS Code screenshot

Step 2. UML Class Diagram

Based on the diagram below, declare each attribute and write a stub for each method. Do not implement any methods yet, but make the code compile.

For example, if a method returns a String, write return ""; as a stub (placeholder).

classDiagram
    class Car {
        - make: String
        - speed: double
        - year: int
        + Car(make: String, year: int)
        + getMake() String
        + getSpeed() double
        + getYear() int
        + accelerate() String
        + brake()
        + equals(obj: Object) boolean
        + toString() String
    }

Note

The brake() method is void (does not return a value). The word void is usually omitted in UML class diagrams.

We recommend showing your code to the instructor or TA before proceeding to the next step.

While you wait, let's take a moment to learn how to use AI tools effectively. Try the following:

AI: Explaining General Concepts ✨

  1. Open your AI tool of choice (e.g., Microsoft Copilot Chat).
  2. Ask the following question: "What does it mean to stub out a method in Java?"
  3. Take a look at the response. Sometimes, the explanation might be overly technical. If so, you can ask for a simpler explanation.
    • Try the following follow-up: "Explain like I'm five."
  4. It is also beneficial to tell the AI to respond in a certain way.
    • Try: "Explain concisely: What does it mean to stub out a method in Java?"
      • This will help you get to the point faster.
    • Try: "Explain to an intro Java dev: What does it mean to stub out a method in Java?"
      • This will help you get an explanation that is more relevant to your current knowledge level.
  5. Always be specific and include relevant context (like the programming language you are using):
    • "What does it mean to declare an attribute in Java?"
    • "How do I interpret a UML diagram in Java?"
    • "How do I determine what package declaration to use in Java?"
  6. Remember, AI tools are here to assist you, but they may not always provide perfect answers. Always verify the information you receive.
    • If you have any questions about the AI responses, feel free to ask the instructor or TA for clarification.

Step 3. Constructor, Getters

The purpose of a constructor is to initialize the attributes of this object. Notice the Car class has three attributes: make, speed, and year. The constructor has two parameters: make and year.

  • Use the parameters to initialize this object's make and year.
  • Initialize this object's speed to zero.
  • Then write the Javadoc comment for the constructor.

Note

When writing documentation for constructors, do not use the word create. Constructors do not "create" objects; the new operator creates an object. Once an object has been created, the constructor is called to initialize the object.

Next, write the three getter methods: getMake(), getSpeed(), and getYear().

  • The purpose of a getter method is to return the current value of an attribute.
  • Notice that the attributes are private, meaning they can be accessed only in the Car class.
    • Other classes, like Main, will need to use the public getters to access the attributes.
  • Implement each getter by returning the corresponding attribute.

Javadoc comments are not required for most getter methods. However, a Javadoc comment is required if a getter does more than simply return an attribute.

Step 4. Test the Constructor

Before implementing the other methods in Car.java, let's make sure the constructor and getter methods work correctly. Open Main.java and define a main method.

Tip

In VS Code, you can type the word main inside the class, press Ctrl+Space (shortcut for "Trigger suggestion"), and press Enter. That will generate the code for main for you.

However, you should memorize how to write a main method on your own, so that you will be able to do so on a written exam, without assistance from VS Code.

Write a Javadoc comment for main, for example:

/**
 * Test the Car class.
 *
 * @param args command-line arguments
 */

Then add the following code to main:

  1. Create two Car objects.
    • Each car should have a different make and year.
  2. Write System.out.println() statements that show the attributes of car:
    • getMake() should return the make you chose.
    • getSpeed() should return zero (at this point).
    • getYear() should return the year you chose.
    • You should have six println statements in total (3 for each car).
  3. Write one more System.out.println(); in the middle to separate the two cars.

Run the Main program by clicking the button or pressing F5. The output should look something like:

Car #1's make: Nissan
Car #1's year: 2003
Car #1's speed: 0.0

Car #2's make: Tesla
Car #2's year: 2025
Car #2's speed: 0.0

AI: Examples, Not Solutions ✨

  1. A great use of AI is to generate examples that illustrate a concept. For instance, you can ask:
    • "Can you provide an example of a Java class with a constructor and getter methods?"
  2. You can analyze and learn from examples in a way that will help you learn to write your own code!
    • This way, you can learn patterns without directly copying code, which is not allowed.
    • In fact, it's a good rule of thumb to never just copy and paste code from anywhere! Always type the code yourself and make sure you understand it.
  3. You can also ask for examples of Javadoc comments. Try this follow-up:
    • "Can you include Javadoc comments in the example?"
  4. Do not ask AI tools to write Javadoc comments for you.
    • Why? The purpose of Javadoc is to communicate with other developers. It's your code that you are writing, so you should be the one communicating what the code's purpose is and how it should be used.

Step 5. Accelerate and Brake

The accelerate() method increases the current speed of the car by 5 miles per hour. After increasing the speed, accelerate() returns a string describing the change. Use the format "15.0 + 5.0 = 20.0" where 15.0 is the old speed and 20.0 is the new speed.

Note

The String.format() method is useful for formatting double values. For example, you can format the speed values to one decimal place as follows:

return String.format("%.1f + 5.0 = %.1f", speed - 5, speed);
Each %.1f in the format string is replaced by an argument. So the first %.1f is the argument speed - 5, and the second %.1f is the argument speed.

Your code must not allow the speed to increase above 150 miles per hour. If the speed is already 150, and accelerate() is called, the speed should remain 150. In that case, the method should return the string "150.0 + 0.0 = 150.0".

The brake() method should decrease the current speed by 5 miles per hour. Your code must not allow the speed to decrease below 0 miles per hour. Notice the brake() method is void, which means no value is returned.

Write Javadoc comments for accelerate() and brake() before moving on to the next step.

Step 6. Test Driving the Car

Add the following code to Main:

  1. Call System.out.println(); to output a blank line.
    • Doing so will separate Step 6's output from Step 4's output.
  2. Call the accelerate() method of the first car object.
    • Print the value returned from accelerate().
    • Call getSpeed(), and print the result.
  3. Call the brake() method of the first car object.
    • Call getSpeed(), and print the result.

The output for this step should look something like:


0.0 + 5.0 = 5.0
Car #1's speed: 5.0
Car #1's speed: 0.0

Step 7. The equals() method

The purpose of the equals() method is to determine if two objects are equivalent. Replace your equals() method with the following partial solution:

@Override
public boolean equals(Object obj) {
    if (obj instanceof Car) {
        Car car = (Car) obj;
        return true;  // TODO compare make and year
    }
    return false;
}

The above code:

  1. Overrides the default implementation of equals().
    • By default, equals() returns true if this and obj are the same object.
  2. Checks if obj, which can be any type of object, is actually a Car object.
    • If not, then equals() returns false at the end by default.
  3. Declares a Car variable named car to reference the same object as obj.

Finish the method by replacing the word true with an expression that determines whether car has the same make and year as this object. In other words, does car.make equal this.make, and does car.year equal this.year?

Warning

In Java, comparing strings using the == operator does not work. You must call one string's equals() method and pass the other string as the argument.

Test your equals() method by adding the following code to Main:

  1. Call System.out.println(); to output a blank line.
  2. Create a third Car object with the same make and year as the first Car object.
  3. Add the following two lines:
    System.out.println("Car #1 equals Car #2: " + car1.equals(car2));
    System.out.println("Car #1 equals Car #3: " + car1.equals(car3));
    

The first line should output false, because the two cars are different. The second line should output true, because the two cars have the same make and year.

AI: Explaining Code ✨

  1. AI can also be used to help you understand parts of your code.
  2. Try the following prompt: "Why should I use .equals() to compare strings in Java instead of the == operator?"
    • You can also include "Explain to an intro Java dev" or "Explain like I'm five" to get a simpler explanation.
  3. What about code that is given to you? You should get into the habit of reading and understanding code that you did not write.
    • But what if you did a first pass and you are still confused?
  4. Copy the code for your entire equals() method, including the method signature.
    • Try: "Explain the following Java code: <paste code here>".
  5. Ask follow-up questions for any muddy points:
    • For example: "What does instanceof do in Java and why do we need it?"
  6. If you ever stumble upon a solution by trial-and-error, you can ask AI to explain it to you!

Step 8: The toString() method

The purpose of the toString() method is to return a string that represents the object. Replace your toString() method with the provided solution:

@Override
public String toString() {
    return String.format("A %d %s that is going %.1f mph",
        year, make, speed);
}

The above code:

  1. Overrides the default implementation of toString().
    • By default, toString() returns the class name and the memory location of the object. For example, "labs.lab03.Car@5b6f7412".
  2. Uses the String.format() method to build a string based on the object's attributes.

Note

Javadoc comments are not required for @Override methods, because the documentation is already defined by the default implementation. In VS Code, you can hover the mouse over a method's name to see the documentation.

Test your toString() method by adding the following code to Main:

  1. Call System.out.println(); to output a blank line.
  2. Call the accelerate() method:
    • One time for the first car.
    • Two times for the second car.
    • Three times for the third car.
  3. Write System.out.println() statements that print each of the car objects.
    • You don't have to call the toString() method. System.out.println(car1) will automatically call the toString() method of car1.

The output should look something like:


A 2003 Nissan that is going 5.0 mph
A 2025 Tesla that is going 10.0 mph
A 2003 Nissan that is going 15.0 mph

AI: Code Review ✨

  1. AI can also be used to help you review your code.
  2. Copy the code for the toString() method.
    • Try the following prompt: "Please review the following Java code: <paste code here>".
  3. Read the summary and suggestions carefully.
    • If you don't understand a suggestion, ask for clarification.
      • For example: "Explain why this change is recommended: <paste suggestion here>".
  4. It will be up to you to decide if the suggestions are valid and/or necessary.
    • Always consider the context and requirements.
  5. For now, do not make any changes to your code based on AI suggestions.
    • You will have a chance to refactor your code in a future lab.

Step 9. Review and Submit

Your final program should call println() 18 times. Therefore, you should have 18 lines of output (including 4 blank lines). If not, double check that you completed the following steps:

  • Step 4: output 7 lines
  • Step 6: output 4 lines
  • Step 7: output 3 lines
  • Step 8: output 4 lines

Tip

You will refer back to this code in a future lab. To make the code easier to remember, add the bullets above as comments to Main.java. For example:

// Step 8: output 4 lines
System.out.println();
car1.accelerate();
car2.accelerate();
car2.accelerate();
...

Submit both Car.java and Main.java to Gradescope. Points will be allocated as follows:

Criterion Points Details
Compile 0 pts Success Required
CompileOfficialTests 0 pts Success Required
Style 2 pts Partial Credit Possible
OfficialTests 8 pts Partial Credit Possible