UC Berkeley CS9G : Java for Programmers
Online Study Guide

Dan Garcia, with help from Mike Clancy and Jeremy Huddleston
Last Upddated : 2009-01-22

Updates to this online document

Table of Contents

Introduction

In CS9G, you learn to program in Java (the course is currently based on Java 5.0). You are assumed to have had previous programming experience, in particular either with object-oriented programming or with a programming language based on C. CS3, CS3S or IDS110 probably do not provide sufficient experience for this course; we recommend that you take CS61A, CS9C, or CS9F to acquire more experience. The course follows our required textbook pretty closely, as we introduce Java fundamentals, then data structures, advanced OOP concepts, exceptions and finally GUIs. We are leaving out a number of important Java topics in this course, and encourage the interested student to pursue these on their own. Among these is threading, applets, serialization, assertions, and enumerations.

Course material consists of quizzes, which test your knowledge of language and low-level conceptual details, and programming assignments, which exercise your overall command of the language. This web site supplies a framework for the course. It contains the following:

Study modules. Each module focuses on a particular programming topic. It provides references to textbook material describing the topic, and suggests exercises for self-study. The study guides reference the following texts:

Head First Java book Required: Head First Java, Second Edition, by Kathy Sierra and Bert Bates (O'Reilly, 2005).

This book is aimed at an introductory audience, but covers advanced Java topics as well. It provides a very nontraditional presentation of Java. Students in recent offerings of CS61B (where the book is also used) have responded quite positively to it. Buy it at a bookstore. O'Reilly sells it for $45 online. You can also read it online if you're logged into a campus machine.

Make sure you check the publisher's online Errata.

Objects to Components with the Java Platform book

Recommended: Objects to Components with the Java Platform, by Art Gittleman (Scott/Jones, 2000).

This book assumes that the reader has programmed in C or C++. Gittleman's explanations are more concise than those of Sierra and Bates. He also includes much material outside the scope of 9G: the Unified Modeling Language used for object-oriented design, uses of Java for networking and database applications, and Java "Beans" (higher-level components for building programs). The Gittleman book may thus prove more useful for your subsequent Java programming. Gittleman also relies heavily on program examples annotated line by line. You should check his presentation before buying the book. Amazon sells it for $66 online.

Programming assignments. Each one has a header page (this tells you the title and related topics) that is followed by the actual assignment.

Sample quiz questions, with solutions. These help you prepare for the quizzes.

Structure of quizzes and programs in CS9G

The following table outlines the relationship between quizzes and programs. All the material for a particular grouping should be completed before material in the next grouping; however, programs within a group must be done before the quiz in that group.

group programs quizzes
A Life 1D Cellular Automaton Fundamentals
B Mad Libs® Data Structures
C Cat and Mouse Advanced Objects and Classes
D Simple RPN Calculator Exceptions
E Cat and Mouse GUI GUI fundamentals

For information about deadlines, consult the Information and Regulations document (available at the Self-paced center).

Program - One-Dimensional Life

This program introduces you to Java by giving you practice with writing a simple program that generates a cool one-dimensional cellular automaton.

Related quizzes

Programming assignment

Readings

Quiz - Fundamentals

You learn the "art" of using Java not only by writing programs of your own, but also by reading those of others. Quiz questions ask you to generate code as well as understand, debug, and criticize already-written code.

Readings

Sample Quiz

These questions are based on the Time class, part of which appears below.

	public class Time {
	
		private int myHours;
		private int myMinutes;
		
		public Time (int hours, int minutes) {
			myHours = hours;
			myMinutes = minutes;
		}
		
		public int getHours ( ) {
			return myHours;
		}
		
		public int getMinutes ( ) {
			return myMinutes;
		}
		...
	}
			
  1. Identify the effect of the following program segments, all to be included within the Time main method. If an error occurs during execution of the program segment, identify the statement that causes the error along with what's wrong.

    program segmenteffect
    Time t;
    t.myHours = 3;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t = null;
    t.myHours = 3;
    t.myMinutes = 25;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t = new Time (12, 30);
    myHours = 3;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t;
    t = new Time (3);
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t = new Time ("12", "30");
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t = null;
    t = new Time (3, 25);
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Time t1 = new Time (3, 30);
    Time t2 = new Time (4, 00);
    Time t3 = t1;
    t1.myMinutes = 13;
    t2.myHours = t3.myHours;
    System.out.println (t1.myHours + ":" + t1.myMinutes);
    System.out.println (t2.myHours + ":" + t2.myMinutes);
    System.out.println (t3.myHours + ":" + t3.myMinutes);
    
  2. Write a public method named extend that, given a Time as argument, extends this Time by the amount of the argument. The extend method should not change the argument time. For example, the program segment below should result in t1 representing the time 3:45.

    	Time t1 = new Time (1, 25);
    	Time t2 = new Time (2, 20);
    	t1.extend (t2);
    
  3. Can extend be written without using getHours and getMinutes? Explain why or why not.

  4. Write a public method named sum that, given a Time as argument, returns a Time object that represents the sum of this Time and the argument. Requirements: sum should not change either this Time or the argument; sum should call extend. For example, the program segment below should result in t1 representing the time 1:25, t2 representing the time 2:20, and t3 representing the time 3:45.

    	Time t1 = new Time (1, 25);
    	Time t2 = new Time (2, 20);
    	Time t3 = t1.sum (t2);
    
  5. Write a public method named checkpoints that returns a six-element array of Time objects. The first array element should be a copy of this Time; the kth element, for k = 1, ..., 5, should be the result of adding 20 minutes to the k-1st element.

Solutions

  1. program segmenteffect
    Time t;
    t.myHours = 3;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Crash trying to set myHours using an uninitialized reference variable.
    Time t = null;
    t.myHours = 3;
    t.myMinutes = 25;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Crash trying to set myHours using a null reference variable.
    Time t = new Time (12, 30);
    myHours = 3;
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Compile-time error: myHours is undeclared.
    Time t;
    t = new Time (3);
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Compile-time error: wrong number of arguments supplied to constructor.
    Time t = new Time ("12", "30");
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Compile-time error: wrong type arguments supplied to constructor.
    Time t = null;
    t = new Time (3, 25);
    System.out.println (t.myHours + ":" + t.myMinutes);
    
    Prints "3:25".
    Time t1 = new Time (3, 30);
    Time t2 = new Time (4, 00);
    Time t3 = t1;
    t1.myMinutes = 13;
    t2.myHours = t3.myHours;
    System.out.println (t1.myHours + ":" + t1.myMinutes);
    System.out.println (t2.myHours + ":" + t2.myMinutes);
    System.out.println (t3.myHours + ":" + t3.myMinutes);
    

    t1 and t3 refer to the same object; thus when t1.myMinutes is set to 13, so is t3.myMinutes. t1 and t3 thus both refer to an object with myHours = 3 and myMinutes = 13. Then we set t2.myHours to 3, resulting in an object with myHours = 3 and myMinutes = 0. Output is

    	3:13
    	3:0
    	3:13
    
  2. Here's an implementation.

    	public void extend (Time t) {
    		myHours = myHours + t.myHours + (myMinutes + t.myMinutes)/60;
    		myMinutes = (myMinutes + t.myMinutes) % 60;
    	}
    
  3. Any method in a class has access to private instance variables in that class. Thus one Time can access another Time's private variables and methods.

  4. Here's an implementation.

    	public Time sum (Time t) {
    		Time rtn = new Time (myHours, myMinutes);
    		rtn.extend (t);
    		return rtn;
    	}
    
  5. Here's an implementation.

    public Time [ ] checkpoints ( )
    	Time [ ] rtn = new Time[6];
    	rtn[0] = new Time (myHours, myMinutes);
    	for (int k=1; k<6; k++) {
    		int h = rtn[k-1].myHours;
    		int m = rtn[k-1].myMinutes;
    		rtn[k] = new Time (h + (m+20)/60, (m+20) % 60);
    	}
    	return rtn;
    }
    

Program - Mad Libs®

This program will give you experience with using different data structures, especially those that are provided by the Java library, by asking you to generate Mad Libs®, a classic word game.

Related quizzes

Programming assignment

Readings

Quiz - Data Structures

In this quiz, you will be tested on elements from the reading. This includes, but is not limited to:

Readings

Sample Quiz

  1. What would you say were the two most important XP techniques?
  2. Answers (any two would suffice, but our favorites are "refactor" and "pair programming"):

  3. What does the following print out?
  4. String ans = "";
    
    for(int i = 0; i < 5; i++) {
        int j = 0;
        while (j <= i) {
            if (j > 2) {
                break;
            }
            ans += "[" + i + j + "]";
            j++;
        }
        ans += "\n";
    }
    
    System.out.println(ans);

    Answer:

    [00]
    [10][11]
    [20][21][22]
    [30][31][32]
    [40][41][42]
    
    
  1. We will show you a succession of statements below that are based on myList, which is either an array or ArrayList. For each statement, indicate what it does, whether myList is an array or ArrayLists, and show how to do the equivalent operation if it were the other data structure.
    1. /* assume myList was empty */ myList.add(a);
    2. String [] myList = new String[2];
    3. myList[1] = null;
    4. myList.size()
  2. Answer:

    1. /* assume myList was empty */ myList.add(a);
      • Adds object a to the ArrayList myList
      • myList[0] = a; // Assumes myList has enough space for one object
    2. String [] myList = new String[2];
      • Initializes array myList to have space for two string references
      • ArrayList<String> myList = new ArrayList<String>();
    3. myList[1] = null;
      • Removes the reference in the second spot of array myList
      • myList.remove(1);
    4. myList.size()
      • Queries the size of the ArrayList myList
      • myList.length
  1. Define a class Countdown that can be initialized with no arguments (default value of the countdown will be 10) or a single argument, a count. The class should provide two zero-argument methods, tick(), which decrements the count by one and the boolean liftoff? which returns true when the count reaches zero. Your Countdown class should use appropriate encapsulation and not send any output to System.out. Then define a CountdownTestDrive class which should create two Countdowns, one with the default value and one with the a countdown of 3. Your output should look like this:
  2. unix% javac Countdown.java CountdownTestDrive.java
    unix% java CountdownTestDrive
    Testing countdown for rocket : Apollo default
    tick
    tick
    tick
    tick
    tick
    tick
    tick
    tick
    tick
    tick
    liftoff!
    Testing countdown for rocket : Apollo 3
    tick
    tick
    tick
    liftoff!
    unix% 

    Answers:

    public class Countdown {
        private int count;
    
        public Countdown() {
            count = 10; // Later, we'll see how to call our other constructor!
        }
    
        public Countdown(int initialCount) {
            count = initialCount;
        }
    
        public void tick() {
            count--;
        }
    
        public boolean liftoff() {
            return(count == 0);
        }
    }
    
    class CountdownTestDrive {
    
        public static void launch(Countdown c, String rocketName) {
    
            System.out.println("Testing countdown for rocket : " + rocketName);
    	
            while(! c.liftoff()) {
        	       c.tick();
    	           System.out.println("tick");
            }
    	       System.out.println("liftoff!");
        }
    
        public static void main(String [] args) {
    	
           	launch(new Countdown(),  "Apollo default");
           	launch(new Countdown(3), "Apollo 3");
        }
    }

Program - Cat and Mouse

This program will give you experience with advanced OOP concepts.

Related quizzes

Programming assignments

Readings

Quiz - Advanced objects and classes

Readings

Sample Quiz

  1. We know an object becomes eligible for Garbage Collection when its last live reference disappears. What are the three ways to get rid of an object's reference?
  2. Answer:

    1. The reference goes out of scope, permanently
    2. The reference is assigned to another object
    3. The reference is explicitly set to null

  3. Why don't interfaces suffer from the multiple inheritance problem? E.g., if there were two separate interfaces that both had a void foo() method, and a class decided to implement both of them, wouldn't there be a problem?
  4. Answer:

  5. A class Shape is defined as follows:
    public class Shape {
        public Shape (int x, int y, int height, int width) {
            myUpperLeftX = x;
            myUpperLeftY = y;
            myHeight     = height;
            myWidth      = width;
        }
    
        public int area() {
            return 0;
        }
    
        private int myUpperLeftX;
        private int myUpperLeftY;
        private int myHeight;
        private int myWidth;
    }
    Indicate what is wrong with the declarations of the myHeight and myWidth fields if we wish to allow an inheriting class (but not any other classes) to access them. Then define a class Rectangle that inherits from Shape. Rectangle's constructor should take the same arguments as Shape's, and Rectangle's area method should return the product of the rectangle's height and width.
  6. Answer:

  7. Consider the following code that uses your solution to the previous exercise:
    Rectangle rect = new Rectangle (1, 20, 10, 5);
    Shape sh = (Shape) rect;
    System.out.println ("area is " + sh.area() );
    Is it legal? If not, explain why not. If it is legal, explain what gets printed and why.
  8. Answer:

  9. Redefine Shape as an abstract class with an abstract area method, and explain why coding Shape as an abstract class is better than coding it as a regular class.
  10. Answer:

  11. Define an interface named TwoDShape, with methods named area, getHeight, and getWidth. Then redefine Rectangle to implement the TwoDShape interface.
  12. Answer:

    public interface TwoDShape {
        public int getHeight();
        public int getWidth();
        public int area();
    }
    
    public class Rectangle extends Shape implements TwoDShape {
    
        public Rectangle (int x, int y, int height, int width) {
            super (x, y, height, width);
        }
    
        public int getHeight() {
            return myHeight;
        }
    
        public int getWidth() {
            return myWidth;
        }
    
        public int area() {
            return myHeight * myWidth;
        }
    }

Program - Simple RPN Calculator

This program will give you experience with exceptions, numbers and have some fun with MIDI events...

Related quizzes

Programming assignments

Readings

Quiz - Exceptions

In this quiz, we will test:

Readings

Sample Quiz

  1. Consider a ListNode class given below (Feel free to do some background reading on Singly-linked lists if you need it)
  2. public class ListNode {
        public int item;
        public ListNode next;
            ...
        public String toString() {
            if (next == null) {
                return item + "";
            } else {
                return item + " " + next.toString();
            }
        }
            ...
    }

    Rewrite the toString method so that it catches NullPointerException and does not do any comparisons of its own.

    Answer:

    public String toString() {
        try {
            return item + " " + next.toString();
        } catch (NullPointerException e) {
            return "";
        }
    }

  3. Name an exception that must be handled/declared, and describe what might cause it to be thrown. Also name an exception that need not be handled/declared, and describe what might cause it to be thrown.
  4. Answer:

    Exceptions that must be handled/declared include anything that is not a subclass of RuntimeException. These could be (there are many more possible answers):

    Exceptions that need not be handled/declared include anything that is a subclass of RuntimeException. These could be (there are many more possible answers):

  5. What follows is code written before Java 5.0. Rewrite it to take advantage of all of the new features in Java 5.0:
  6. public void foo() {
        ArrayList listOfNumbers = new ArrayList();
        listOfNumbers.add(new Integer(3));
        Integer one = (Integer) listofNumbers.get(0);
        int intOne = one.intValue();
    }
    

    Answer:

    What we've gained in Java 5.0 that are relevant to the problem are:

    public void foo() {
        ArrayList<Integer> listOfNumbers = new ArrayList<Integer>();
        listOfNumbers.add(3);
        int intOne = listofNumbers.get(0);
    }
    

  7. Label each of the following statements as either true or false.
    1. A static method cannot access a static variable.
    2. A final static variable must be assigned a value at declaration, because its value cannot be changed.
    3. A final method cannot be overriden.
    4. A final class cannot be extended.
    5. A static variable means it is not dynamic, i.e., it cannot be changed.
    6. A static variable may be initialized at any time; perhaps after several objects of the class have been created.

    Answer:

    1. FALSE. A static method can access a static variable. E.g., if Math.tan() needed Math.PI, it could use it.
    2. FALSE. A final static variable must be assigned a value at declaration OR in a static block. (It's true that its value cannot be changed after that, though)
    3. TRUE. A final method cannot be overriden.
    4. TRUE. A final class cannot be extended.
    5. FALSE. A static variable can be changed; it is a shared variable among all objects of a class. It's also sometimes known as a class variable, because it is associated with the class, not any particular object.
    6. FALSE. All static variables in a class are initialized before any object of that class can be created.

Program - Cat and Mouse GUI

This program will give you experience with advanced OOP concepts.

Related quizzes

Programming assignments

Readings

Quiz - GUI Fundamentals

For this quiz, you will learn about GUI programming in Java:

Readings

Sample Quiz

  1. You be the layout manager. Sketch what the GUI will look like if we run the following snippet of code (assume we've set up the headers correctly and added the appropriate methods to the frame to tell it the size, visible flag and DefaultCloseOperation) and then resize the window to be bigger (in both horizontal and vertical directions):
  2. 	JFrame frame = new JFrame();
    
    	JPanel panelWest  = new JPanel();
    	JPanel panelEast  = new JPanel();
    	JPanel panelSouth = new JPanel();
    
    	JButton b1 = new JButton("1");
    	JButton b2 = new JButton("2");
    	JButton b3 = new JButton("3");
    	JButton b4 = new JButton("4");
    
    	JButton b5 = new JButton("5");
    	JButton b6 = new JButton("6");
    	JButton b7 = new JButton("7");
    	JButton b8 = new JButton("8");
    	JButton b9 = new JButton("9");
    
    	JButton ba = new JButton("a");
    	JButton bb = new JButton("b");
    	JButton bc = new JButton("c");
    
    	frame.getContentPane().add(BorderLayout.CENTER, b1);
    	frame.getContentPane().add(BorderLayout.NORTH,  b2);
    	frame.getContentPane().add(BorderLayout.EAST,   b3);
    	frame.getContentPane().add(BorderLayout.SOUTH,  b4);
    	frame.getContentPane().add(BorderLayout.WEST,   panelWest);
    
    	panelWest.setLayout(new BorderLayout());
    	panelWest.add(BorderLayout.CENTER, b5);
    	panelWest.add(BorderLayout.NORTH,  b6);
    	panelWest.add(BorderLayout.EAST,   panelEast);
    	panelWest.add(BorderLayout.SOUTH,  panelSouth);
    	panelWest.add(BorderLayout.WEST,   b7);
    
    	panelEast.setLayout(new BoxLayout(panelEast, BoxLayout.Y_AXIS));
    	panelEast.add(b8);
    	panelEast.add(b9);
    
    	panelSouth.add(ba);
    	panelSouth.add(bb);
    	panelSouth.add(bc);
    

    Answer:

    These questions are actually pretty easy. We see the top-level Frame is a BorderLayout with 1,2,3 and 4 placed in the CENTER, N, E and S spots respectively. The W spot is a panel which is also a BorderLayout (recall the default layout for a Panel is FlowLayout). It has buttons 5,6 and 7 placed in its CENTER, N and W slots. Its E slot is yet another Panel, but this time it's BoxLayout with a vertical stack. So that covers 8 and 9. The S panel has default placement (FlowLayout, which means L to R and wrap when needed), so we place a, b and c on the bottom of the inner Border's south slot (same width as the 6 in the north slot) , L to R.

  3. Complete the following code to author a simple GUI that counts how many times a button (labeled "Click me") has been clicked and displays that number below the button saying: "i clicks", where i should be a number from 0 (at startup) to the number of clicks. Try to write it in the fewest number of lines. Here's a screenshot of what it should look like at startup:



    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Clicker ___________________________________  {
    
    
    
    
        public static void main (String [] args) {
            Clicker gui = new Clicker();
            gui.go();
        }
    
        public void go() {
    
    
    
    
    
    
    
    
    
    
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(100,100);
            frame.setVisible(true);
        }
    
    
    
    
    
    }
  4. Answer:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    
    public class Clicker implements ActionListener {
    
        JLabel iLabel;
        int i = 0;
    
        public static void main (String [] args) {
            Clicker gui = new Clicker();
            gui.go();
        }
    
        public void go() {
    
            JFrame  frame       = new JFrame();
            JButton button      = new JButton("Click me");
            iLabel              = new JLabel("" + i);
            JLabel  clicksLabel = new JLabel("clicks");
            button.addActionListener(this);
    
            frame.getContentPane().add(BorderLayout.NORTH,  button);
            frame.getContentPane().add(BorderLayout.CENTER, iLabel);      // or WEST...
            frame.getContentPane().add(BorderLayout.EAST,   clicksLabel); // and CENTER
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(100,100);
            frame.setVisible(true);
        }
    
        public void actionPerformed(ActionEvent event) {
            iLabel.setText("" + ++i);
        }
    }

  5. What is the reason we often use inner classes with GUIs?
  6. Answer:

    Well, since we can't implement a method with the same signature more than once in a class (how would the system know which one to invoke?), we often get stuck because the ActionListener interface can ony be implemented once. However, we will probably need to get action events for more than one GUI element (say, two buttons). We have no way (except option two on page 373 which breaks the beautiful OO paradigm) to have two different listeners that have access to our internal state. Inner classes are the beautiful solution, in that they allow us to have multiple listener classes which all implement the ActionListener interface, and all have access to our GUI's instance variables.

  7. Now, we'd like to build a GUI that animates a ball (with diameter of DIAMETER) bouncing left and right in a box (outer length OUTER, overall distance traveled each bounce INNER), faster and faster, doubling in speed with every bounce until it jumps off the screen. Note, we wrote this code in a rush, there may be bugs in it! Your job is to find them and identify whether they are syntax, logical, or style bugs, then correct all the bugs...



    import java.awt.*;
    
    public class Bounce {
    
        int x = 0;
        public static final int DIAMETER = 100;
        public static final int OUTER    = 356; // some power of 2 + DIAMETER
        public static final int INNER    = OUTER - DIAMETER;
    
        public static void main (String [] args) {
            JFrame      frame     = new JFrame();
            MyDrawPanel drawPanel = new MyDrawPanel();
    
            frame.add(BorderLayout.CENTER, drawPanel);
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(OUTER, DIAMETER);
            frame.setVisible(true);
    
            int speed = 0;
            while(Math.abs(speed) <= INNER) { // can't jump out in 1 step
                while(0 <= x && x <= INNER) { // x is still inside box
                    paintComponent(g);
                    Thread.sleep(5);
                    x += speed;
                }
                x     -= speed; // Step back (the last while stepped out)
                speed *= -2;    // Double speed but reverse direction
            }
        }
    
        class MyDrawPanel extends JPanel {
            public void paintComponent(Graphics g) {
                g.setColor(blue);
                g.fillOval(x, 0, DIAMETER, DIAMETER);
            }
        }
    }
    
    
  8. Answer:

    Here are the problems we found (the corrected solution is below)

    1. Syntax: We forgot to include "import javax.swing.*"
    2. Syntax: This one is subtle -- you might remember from the days when you learned about static and non-static methods that non-static instance variables (here, x) can't be referenced from a static method. Well, we're doing that here. We've got to wrap all of our GUI code (that uses x) in a non-static method, say, go.
    3. Style: It's more appropriate to add the panel to the pane than the frame directly. See HFJ 2/e p.354.
    4. Logical: We have to initialize speed with 1 (or a non-zero number) if we're going to increase it with multiplication
    5. Syntax: paintComponent() is NEVER called explicitly by the user (see HFJ 2/e p. 364). We call the drawing panel's repaint and it takes care of calling paintComponent for us.
    6. Syntax: We have to wrap the Thread.sleep() call around a try/catch block because it'll throw a java.lang.InterruptedException which must be caught or thrown.
    7. Logical: We need to erase what was already there, otherwise we'll get smeared results.
    8. Syntax: blue is an unbound variable; we have to use Color.blue here.

    import javax.swing.*;                 ### bug 1
    import java.awt.*;
    
    public class Bounce {
    
        int x = 0;
        public static final int DIAMETER = 100;
        public static final int OUTER    = 356; // some power of 2 + DIAMETER
        public static final int INNER    = OUTER - DIAMETER;
    
        public static void main (String [] args) {
            Bounce gui = new Bounce();   ### bug 2
            gui.go();                    ### bug 2
        }                                ### bug 2
    
        public void go() {               ### bug 2
            JFrame      frame     = new JFrame();
            MyDrawPanel drawPanel = new MyDrawPanel();
    
            frame.getContentPane().add(BorderLayout.CENTER, drawPanel); ### bug 3
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(OUTER, DIAMETER);
            frame.setVisible(true);
    
            int speed = 1;               ### bug 4
            while(Math.abs(speed) <= INNER) { // can't jump out in 1 step
                while(0 <= x && x <= INNER) { // x is still inside box
                    drawPanel.repaint(); ### bug 5
                    try {                ### bug 6
                        Thread.sleep(5);
                    } catch(Exception ex) { }
                    x += speed;
                }
                x     -= speed; // Step back (the last while stepped out)
                speed *= -2;    // Double speed but reverse direction
            }
        }
    
        class MyDrawPanel extends JPanel {
            public void paintComponent(Graphics g) {
                g.setColor(Color.white);                             ### bug 7
                g.fillRect(0, 0, this.getWidth(), this.getHeight()); ### bug 7
                g.setColor(Color.blue);                              ### bug 8
                g.fillOval(x, 0, DIAMETER, DIAMETER);
            }
        }
    }