- Problem 1: Choosing and Setting-Up a Development Environment
- Problem 2: Obtaining files from GitLab
- Problem 3: Warm-Up Exercise—HolaWorld
- Problem 4: Your first Java class—RandomHello
- Problem 5: Testing Java Code with JUnit
- Problem 6: Answering Questions About the Code
- Problem 7: Getting a Real Taste of Java—Balls and Boxes
- Problem 8: Turning In Your Homework
- What to Turn In
- Optional: Debugger Tutorial
The purpose of this homework is to help you set up your development environment, get reacquainted with Java, and start getting familiar with tools you will use for the rest of the course. Although the homework description is long, we expect the step-by-step instructions will make doing the homework less overwhelming than reading it may be.
This homework links to (the middle of) some other handouts at many points. For convenience, here is the list of these handouts:
- Working At Home
- Editing, Compiling, Running, and Testing Java Programs
- Eclipse Reference for CSE331
- Version Control Reference
- Assignment Submission (explains how to validate what you submit)
- Java Style Guide for CSE331
(It also links to various Java files and API documentation files that are not listed above.)
You are free to get help from anyone on any portion of this homework. That is, the standard collaboration policy does not apply to this homework. You will need to know this material for the remainder of the quarter, however, so make sure you understand thoroughly the tools and concepts in this homework.
We encourage you to finish this homework well before its due date. If you are having trouble with finishing on time, get in touch with the staff immediately so we can help you get back on track.
You first need to decide what computer(s) and development environment(s) you will use for the course, or at least for this homework. We strongly recommend using the Eclipse IDE in CSE331, but we will not check whether or not you do so. We also provide instructions for working from the Linux command line.
You can use the CSE department’s instructional labs by going to the basement of the Allen Center; or access the facilities remotely; or install a virtual machine on your own computer that is just like the department’s Linux machines; or install Java, Eclipse, and other necessary tools on your own computer. If you choose to work from home on your personal machine please follow the basic setup instructions to set up your development environment. For more information and trade-offs among these choices: the Working At Home document explains the trade-offs and provides the instructions for each option. Note that even if you mostly do not use the department’s machines, you should still connect to
attu to validate your assignment after you submit it, as described near the end of this homework.
Once you have chosen a development environment, you should set it up for CSE331 use. See the Starting Eclipse instructions. (Note: if you switch development environments later in the quarter, revisit these instructions.)
Using the correct compiler: Eclipse is a widely-used Java development environment with a number of excellent features including integration with Git, Ant, and JUnit — tools that we use in CSE331. However, instead of using the official Java compiler (“javac”) from Oracle/Sun, Eclipse uses an Eclipse-specific Java compiler. Bugs in either compiler are very rare, but if they occur they can cause the same code to have different behavior with different compilers. Course staff will compile and grade your code using the
javac compiler, so you should make sure that your code behaves correctly when compiled with
javac. One way to verify this is to use the Ant build file we provide for each homework. See Compiling Java Source Files for details.
Refer to the Eclipse quick reference to learn about some of Eclipse’s handy features.
Throughout the course, you will receive starter code and submit your assignments through CSE’s GitLab server (git). git is a version control system that lets software engineers backup, manage, and collaborate on large software projects. GitLab is a CSE department server that provides git repositories for students in CSE331 and many other classes and projects (You will learn more about git in section.)
For this problem, you should follow the setup instructions in the Version Control handout, which describes how to “clone” (copy) your CSE331 GitLab repository to a local machine. This handout also contains instructions for pulling from, committing to, and tagging your repository. You should familiarize yourself with these commands as you will need to use them throughout this homework and the rest of the course.
For this problem, you will fix some buggy code we provide.
See Editing and Compiling Source Files to help learn how to perform the following basic tasks: adding new files to your directory structure, compiling Java code, and reading the Java compiler’s output (which may indicate errors).
Also see the CSE331 Java Style Guide, which describes some standards for Java style that we will expect you to follow.
Try to compile the provided code in
HolaWorld.java. You should see compilation errors for this file. (And possibly in
hw3/test/RandomHelloTest.java too; if so, ignore these for now since we will fix them in the next part.) In particular, the lines:
are problematic. (If you’re using the the Ant builder, you may see the second error only after you’ve fixed the first one.) If you are using Eclipse, these errors will be marked with red squiggly lines in
HolaWorld.java itself will be marked with a red crossmark in the Package Explorer.
Fix these errors and run
After you’ve fixed the errors and run the code, it would be a good time to commit your changes to GitLab.
Create a Java class with a
main method that will randomly choose, and then print to the console, one of five possible greetings that you define.
Create the file
RandomHello.java, which will define a Java class
RandomHello that will reside in the Java package
hw3; that is, its file name is
Java requires every runnable class to contain a
main method whose signature is
public static void main(String args) (for example, the
main methods in
HelloWorld and in
A code skeleton for the
RandomHello class is shown below. Eclipse will generate some of this skeleton for you when you create the new
This skeleton is meant only to serve as a starting point; you are free to organize it as you see fit.
Don’t write your own random number generator to decide which greeting to select. Instead, take advantage of Java’s Random class. (This is a good example of the adage “Know and Use the Libraries” as described in Chapter 7 of Joshua Bloch’s Effective Java. Learning the libraries will take some time, but it’s worth it!)
Type the following into the body of your
Random randomGenerator = new Random();
This line creates a random number generator (not a random number, which comes later, but a Java object that can generate random numbers). In Eclipse, your code may be marked as an error by a red underline. This is because the
Random class is defined in a package that has not yet been imported (
hw3 are the only packages that are implicitly imported). Java libraries are organized as packages and you can only access Java classes in packages that are imported. To import
java.util.Random, add the following line under the line
package hw3; at the top of your file (after the
package hw3; declaration):
This will import the class Random into your file. To automatically add all necessary imports and remove unused imports, Eclipse lets you type CTRL-SHIFT-O to *Organize* your imports. Because there is only one class named
Random, Eclipse will figure out that you mean to import
java.util.Random and will add the above line of code automatically. (If the name of the class that needs to be imported is ambiguous — for example, there is a java.util.List as well as a java.awt.List — then Eclipse will prompt you to choose the one to import.)
Read the documentation for
nextInt(int n) method by going to the Java API and selecting
Random from the list of classes in the left-hand frame. Many classes also let you pull up documentation directly in Eclipse. Just hover over the class or method name and press SHIFT+F2.
nextInt(int n) method to choose your greeting. You don’t have to understand all the details of its behavior specification, only that it returns a random number from 0 to n-1.
One way to choose a random greeting is using an array. This approach might look something like:
String greetings = new String; greetings = "Hello World"; greetings = "Hola Mundo"; greetings = "Bonjour Monde"; greetings = "Hallo Welt"; greetings = "Ciao Mondo";
main method in the skeleton code above prints the value returned by
getGreeting. So if you insert code in
getGreeting to select a greeting randomly, when the class is run it will will print that greeting.
When you are finished writing your code and it compiles, run it several times to ensure that all five greetings can be displayed.
Again, now it would be a good idea to add your new class to version control and commit your code.
Testing is essential for writing quality software, so it’s important for testing to be a convenient part of software development. JUnit is a framework for creating unit tests in Java. A unit test is a test for checking that a given method in a class conforms to its specification for an input. This problem provides a quick overview and simple example of how JUnit works. (Unit testing will be more significant in later assignments.)
Now run the JUnit test
A window or panel with a menacing red bar will appear, indicating that some of the tests in
FibonacciTest did not complete successfully (see screenshot at right). The top pane displays the list of tests that failed, while the bottom pane shows the Failure Trace for the highlighted test. The first line in the Failure Trace should display an error message that explains why the test failed. (The author of the test code creates this error message.)
If you click on the failure
testThrowsIllegalArgumentException, the bottom pane will switch to the appropriate error message. In this example, the first line of the failure trace shows that
Fibonacci.java improperly threw an
IllegalArgumentException when tested with zero as its argument. (You may have to scroll to the right to see this.) If you double-click on the name of a test in the top pane, Eclipse will jump to the line where the failure occurred in the editor pane. Figure out the problem in
Fibonacci.java, fix it, and rerun the JUnit test. Eclipse will automatically rebuild when you make changes, but if you are running JUnit from the command line, you must manually rebuild (compile)
Fibonacci.java before you rerun JUnit. This can be done by rerunning the
ant command (which also compiles the files) or by following the compiling instructions and then clicking the “Run” button.
Use the information in the Failure Trace box to help you continue debugging
Fibonacci. Keep a record of what you did to debug
Fibonacci as you will have to answer questions about your debugging experience in the next problem. After you have fixed all the problems in
Fibonacci, you should see a bright green bar instead of a red one when you run
Now look at the JUnit tests that we wrote for
RandomHello. They are called
RandomHelloTest, respectively. Ensure that your modified code passes these tests before you turn in your homework.
Find the file named
hw3/answers.txt in your
hw3 folder. Open this file and add answers to the following questions under Problem 6:
- Why did Fibonacci fail the testThrowsIllegalArgumentException test? What (if anything) did you have to do to fix it?
- Why did Fibonacci fail the testBaseCase test? What (if anything) did you have to do to fix it?
- Why did Fibonacci fail the testInductiveCase test? What (if anything) did you have to do to fix it?
Until now, we have only been introducing tools. This problem delves into a real programming exercise. This problem will likely be somewhat challenging for most of you. Don’t be discouraged. We’re here to help, and we expect that time spent now will pay off significantly during the rest of the course.
As you work on this problem, record your answers to the various questions in the
answers.txt that you first edited in the previous section of this assignment.
Warm-Up: Creating a Ball:
- What is wrong with
Ball.java? Fix the problems with
Ball.javaand document your work in
We have included a JUnit test BallTest to help you. Moreover, one of Eclipse’s warnings should help you find at least one of the bugs without even referring to the JUnit results.
- What is wrong with
Using Pre-Defined Data Structures:
Next, create a class BallContainer. As before, skeleton code is provided (see BallContainer.java). A BallContainer is a container for Balls. BallContainer should support the following methods: your task is to fill in the code to implement these methods correctly:
The specifications for these methods are found in the javadoc file for BallContainer.
In BallContainer, we use a java.util.Set to keep track of the balls. This is a great example of using a predefined Java data-structure to save yourself significant work. Before implementing each method, read the documentation for
Set. Some of your methods will be as simple as calling the appropriate predefined methods for Set.
To help you out, we have included a JUnit test called BallContainerTest.java.
Before you start coding, please take time to think about the following question (which you need to answer in the text file):
There are two obvious approaches for implementing getVolume():
- Every time
getVolume()is called, go through all the Balls in the
Setand add up the volumes. (Hint: one solution might use a for-each loop to extract
Balls from the
- Keep track of the total volume of the Balls in
BallContainerwhenever Balls are added and removed. This eliminates the need to perform any computations when
Which approach do you think is the better one? Why?
- Every time
Implementing a Box:
In this problem, you will do a little more designing and thinking and a little less coding. You will implement the Box class. A Box is also a container for Balls. The key difference between a
BallContaineris that a Box has only finite volume. Once a box is full, we cannot put in more Balls. The size (volume) of a Box is defined when the constructor is called:
public Box(double volume);
Boxis in many ways similar to a
BallContainer, we internally keep track of many things in the
BallContainer, allowing us to reuse code. Many of the methods in
Boxcan simply “delegate” to the equivalent in
BallContainer. For example, removing from a
Boxcannot cause it to exceed its volume limit. This design of having one class contain an object of another class and reusing many of the methods is called composition.
(Optional Note: You may wonder why we did not make
BallContainervia inheritance. That is, why did we not make
Boxa subclass of
BallContainer? We will discuss this much more deeply later in the course, but the key idea is that
Boxis not what we call a true subtype of
BallContainerbecause it is in fact more limited than
Boxcan only hold a limited amount); hence, a user who uses a
BallContainerin his code cannot simply substitute that
Boxand assume the same behavior. (The code may cause the Box to fill up, but he did not have this concern when using a
BallContainer). For this reason, it is unwise to make
In addition to the constructor described above, you will need to implement the following new methods in
The specifications for these methods can be found in the javadoc file for Box.
A few things to consider before you start writing code:
- You shouldn’t need to implement your own sorting algorithm. Instead, take advantage of the Java API (remember: “Know and Use the Libraries”).
- Also, you shouldn’t need to change your implementation of
Ballfor this problem. In particular, you should not implement the Comparable interface. If you are tempted to do so, consider using Comparator instead.
Comparatoris a companion interface to
Comparableand is used throughout the Java libraries: check out the sort methods in java.util.Collections as an example.
- If you do make any changes to
Ballfor this problem, then explicitly document what changes you made and why in
- Be cautious if you plan on using Java’s
TreeSet; remember that
TreeSetdoes not store duplicates, and if you provide a
Comparator, it will use that
Comparatorto determine duplication. See the TreeSet API documentation for more details.
- Before you start working on
getBallsFromSmallest(), we recommend strongly that you consider using Iterator.
- The JUnit test BoxTest should help you. However, we do not guarantee that the tests we provide will catch all bugs.
- And, naturally, don’t forget to commit your code more than occasionally.
Also, answer the following questions in your
- There are many ways to implement
getBallsFromSmallest(). Briefly describe at least two different ways. Your answers should differ in the implementation of
Box, not in lower-level implementation (for example, using an insertion sort instead of a selection sort is a lower-level implementation because it does not affect how
Boxis implemented). Hint: think about different places in the
Boxclass where you could add code to achieve the desired functionality.
- Which of the above ways do you think is the best? Why?
There is no one correct answer. Our intent is to help you fight that urge to code up the first thing that comes to mind. Remember: More thinking, less coding.
Each homework will indicate exactly what to turn in a Section titled “What to Turn In”. This typically includes Java source files (that you change or create) and text files.
You will turn in your homeworks by committing changes and pushing those changes to your GitLab repository. To do so,
- Add and commit all changed (or newly-added) files.
- Push the committed changes to the repository so they are stored in GitLab as well as being updated locally.
You can commit and push changes as many times as you want while working on the assignment. That is a good way to store backup copies of your work in the CSE GitLab repository.
When you have committed and pushed all of your changes and are done with the assignment, you should create a git tag in your repository named
hw3-final and push that tag to your repository. Once you have committed and pushed that tag, your assignment has been submitted. The staff will grade the files in your repository that are labeled with that tag. Be sure you remember to add/commit/push your files and the tag!
For each homework, we strongly recommend that you validate what you have turned in by running the provided validation checks on
attu. Read about validate now and be sure to get it working for the sake of this and future homeworks. While validate does not ensure your homework is perfect, it performs important sanity checks, like seeing if your code compiles and if expected files are present in the repository.
As the detailed instructions for validate indicate, you want to make sure
validate completes without errors. If validation was successful, the output will end with something like:
... BUILD SUCCESSFUL Total time: 9 seconds
If there is a problem, the output will end with something like:
... BUILD FAILED /homes/iws/username/workspace331/cse331/src/common.xml:129: exec returned: 1
and will indicate, before that, what is wrong. Read the output carefully to find this information.
Validate your homework and fix problems as many times as necessary until there are no errors. You have now successfully turned in your CSE331 homework.
Your TA should be able to find the following in the
src directory of Gitlab:
hw3/HolaWorld.javathat works as described in Problem 5 with no compilation errors
hw3/RandomHello.javathat prints out one of five random messages when its
mainmethod is executed
hw3/Fibonacci.javathat passes the three tests in
hw3/test/FibonacciTest.java(Note that you should not edit
hw3/test/FibonacciTest.javato accomplish this task.)
hw3/Box.javathat pass their respective JUnit tests (Again, you should not modify the JUnit tests, though you are encouraged to read the code to understand what they test.)
hw3/answers.txtcontaining answers to the questions in Problems 6 and 7.
Please include your first and last name in every text file you turn in (i.e., files ending with
.txt). In particular, be sure to update
answers.txt to include your name as well as the expected answers.
In this part, you will learn about Eclipse’s built-in debugger. A debugger can help you debug your program by allowing you to “watch” your program as it executes, one line at a time, and inspect the state of variables along the way. Using a debugger can be much more powerful and convenient than littering your program with statements that print output.
One of the most useful features of a debugger is the ability to set breakpoints in your program. When you run your program through the debugger, it will pause when it reaches a line with a breakpoint. You can inspect the current state of variables, then continue running your program normally or step through one line at a time to watch the variables change.
Adder.java. This simple program is supposed to print the sum of two user-provided integers. Try running it a few times (or reading the source code) and you’ll see that it doesn’t behave as expected.
- Double-click in the left-hand margin of the class next to the line
return x - y;A blue circle should appear, indicating a breakpoint. (Double-clicking again removes the breakpoint.)
- Run the program in debug mode by using F11,
Run >> Debug, or the green bug icon in the toolbar. As before, enter two ints (say, 3 and 4) in the console when prompted. When your program hits the breakpoint, Eclipse asks if you want to open the Debug perspective. Choose yes.
The debug perspective looks overwhelming at first, but don’t worry! In the top-right panel, select the “Variables” tab and you’ll see the names and values of all variables in the current context. The top-left panel (“Debug”) shows where the program is currently paused, where the current method was called, and so on. (This is called the stack trace). Double-click on a method name to see the corresponding line in the panel below, where you can view and edit your source code. Finally, the bottom-left panel shows the console window.
What are all the names and values listed in the “Variables” panel? What does the “Debug” panel list as the current method and line number? (Write down the text that was highlighted when the Debug perspective first opened.)
Immediately above the “Debug” panel are several buttons for running your program. Mouse over each one for a description. “Resume” (green arrow) causes your program to continue executing normally until it finishes or hits another breakpoint. If you want to monitor what happens shortly after the breakpoint, use “Step Into” and “Step Over” (yellow arrows). “Step Over” executes the current line and pauses on the next line. “Step Into” enters any method called on the current line so you can execute that method line-by-line. (To finish the current method and jump back to the caller, use “Step Out.”) Hit “Step Over” once to execute the
returnstatement and exit
computeSum. Hit “Step Over” again to progress to the next line.
What are all the names and values listed in the “Variables” panel after each of the two step overs?
Hit “Resume” to allow the program to finish executing. Return to the default Java perspective by clicking “Java” in the top-right corner or by going to
Windows >> Open Perspective >> Other...and selecting Java (default).