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:
- Create a
lab03
folder under yoursrc/labs
folder. - Add two new files:
Car.java
andMain.java
. - Write the
package
andpublic class
statements. - Write a Javadoc comment with your name and date.
When finished, your Car.java
and Main.java
should look like this:
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 ✨
- Open your AI tool of choice (e.g., Microsoft Copilot Chat).
- Ask the following question:
"What does it mean to stub out a method in Java?"
- 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."
- Try the following follow-up:
- 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.
- Try:
- 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?"
- 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'smake
andyear
. - Initialize
this
object'sspeed
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 theCar
class.- Other classes, like
Main
, will need to use thepublic
getters to access the attributes.
- Other classes, like
- 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
:
- Create two
Car
objects.- Each car should have a different make and year.
- 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).
- 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 ✨
- 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?"
- 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.
- You can also ask for examples of Javadoc comments. Try this follow-up:
"Can you include Javadoc comments in the example?"
- 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);
%.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
:
- Call
System.out.println();
to output a blank line.- Doing so will separate Step 6's output from Step 4's output.
- Call the
accelerate()
method of the first car object.- Print the value returned from
accelerate()
. - Call
getSpeed()
, and print the result.
- Print the value returned from
- Call the
brake()
method of the first car object.- Call
getSpeed()
, and print the result.
- Call
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:
- Overrides the default implementation of
equals()
.- By default,
equals()
returns true ifthis
andobj
are the same object.
- By default,
- Checks if
obj
, which can be any type of object, is actually aCar
object.- If not, then
equals()
returns false at the end by default.
- If not, then
- Declares a
Car
variable namedcar
to reference the same object asobj
.
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
:
- Call
System.out.println();
to output a blank line. - Create a third
Car
object with the same make and year as the firstCar
object. - 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 ✨
- AI can also be used to help you understand parts of your code.
- 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.
- You can also include
- 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?
- Copy the code for your entire
equals()
method, including the method signature.- Try:
"Explain the following Java code: <paste code here>"
.
- Try:
- Ask follow-up questions for any muddy points:
- For example:
"What does instanceof do in Java and why do we need it?"
- For example:
- 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:
- 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"
.
- By default,
- 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
:
- Call
System.out.println();
to output a blank line. - Call the
accelerate()
method:- One time for the first car.
- Two times for the second car.
- Three times for the third car.
- 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 thetoString()
method ofcar1
.
- You don't have to call the
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 ✨
- AI can also be used to help you review your code.
- Copy the code for the
toString()
method.- Try the following prompt:
"Please review the following Java code: <paste code here>"
.
- Try the following prompt:
- 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>"
.
- For example:
- If you don't understand a suggestion, ask for clarification.
- It will be up to you to decide if the suggestions are valid and/or necessary.
- Always consider the context and requirements.
- 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 |