CS115 lecture notes, Spring 1999 Week 8, Friday QUIZ MONDAY on Chapter 8 Debugging tips -------------- 1) Avoid random-walk programming. Don't make changes just for the sake of making changes. There are two good reasons for making a change: a) you think you know what is wrong and you think you know how to fix it. You have to have a hypothesis. b) you are not sure what is wrong, but you want to test a variation of the program in order to get more information about what it is going. In this case, you might not have a hypothesis, but you should have a specific question in mind that you want answered. For example: is this method getting executed? What is the parameter when this gets executed? What is the value of this variable in this place? The more specific the question, the more likely you will be able to answer it. 2) Read your program back before you run it. When you make a change, re-read the program and think about what it does before you try it. 3) At the beginning of a recursive method, add a print statement that prints the parameters. That way when the program runs it will generate a stack diagram for you! 4) In the body of a loop, add a print statement that prints the value of the loop variable(s). That way the program generates an interation table for you. 5) If you get a StringIndexOutOfBounds exception, look at the error message to see WHERE in your program it occurred. Once you find the offending statement, add a print statement before it. Check the value of the index before you use it. Interesting objects (continued) ------------------- Although Strings are objects, they are atypical objects. Now we're going to talk about interesting objects. An object is a collection of storage locations that contain related information. Each storage location has a name, a type and a value, just like a variable. For example, a Point is an object that contains two storage locations, both have type int. They are named x and y. Point is an object type in Java. That means that you can create a variable with type Point. Point blank; The problem is that creating a Point variable does not create a Point object. In order to create a Point object, you have to use the new command: blank = new Point (3, 4); Draw the diagram of these two statements. Strictly speaking, the value of blank is a REFERENCE to the object that contains the values 3 and 4. The object that blank refers two contains two storage locations. The object that blank refers two is called an instance. The storage locations inside the object are called instance variables. Every Point object is an instance of the Point class. Every Point variable should refer to a Point object. Instance variables ------------------ You can access the instance variables of an object using dot notation. int x = blank.x; This would set x to 3. You can modify the instance variables of an object. blank.x = blank.x + 3; Alternate form of the new command --------------------------------- Point blank = new Point (3, 4); Create a new instance of the Point class and initializes the instance variables. Returns a reference to the new object and stores it in blank. Blank now refers to the new object. Passing objects as parameters ----------------------------- public static void printPoint (Point p) { System.out.println ("(" + p.x + ", " + p.y + ")"); } This method take a single Point as an argument, and prints the instance variables in a nice format. You would invoke it like this: Point blank = new Point (3, 4); printPoint (blank); As usual, the name of the argument has nothing to do with the name of the parameter. Draw a stack diagram of this method being invoked. blank (in main) and p (in printPoint) are different Point variables that refer to the same Point object. That's ok. In fact, that's what makes it possible for the two methods to share information. (Someone last time asked if objects are a way to make information globally accessible. The answer is sort of -- they allow you to share containers between methods). The usual rules of composition apply: printPoint (new Point (3, 4)); The thing in parentheses is an expression with type Point, and is therefor a legal argument for the printPoint method. A second kind of object ----------------------- Java also has a built-in Rectangle object. A Rectangle object has nothing to do with the rectangles we draw on the screen. You cannot draw a Rectangle object and you cannot see it. A rectangle object is four integers. Nothing more, nothing less. The names of the instance variables are x, y, width, and height. You can create a Rectangle without initializing the instance variables: Rectangle box = new Rectangle (); And then you can fill in the instance variables: box.x = box.y = ... Or you can do both at the same time: Rectangle box = new Rectangle (0, 0, 100, 200); In both cases the picture is the same. Another way to get a Rectangle object is to invoke the getBounds method: public void paint (Graphics g) { Rectangle bbox = getBounds (); // find the window size paintBox (g, 0, 0, bbox.width, bbox.height); // draw something! } This only works when there is a Graphics window. You create the variable bbox, but the Java system creates the Rectangle object that contains the bounds. We extract the instance variables of this Rectangle using do notation.