Programming 101
By Way of Java
Instructor: T. Boutell
Transcript for 11/21/96
Stimulants Anonymous
Welcome to the Java programmers' roasteria. A wide variety of stimulating beverages are consumed among the whirring virtual machines.
You say, "Welcome to the fifth installment of the Java Class."
You say, "thanks for coming."
You say, "tonight we're going to talk about one of a few remaining major java language features we haven't touched on."
You say, "that's not to imply that we're almost done covering java in general, because there are lots of class libraries we haven't touched."
You say, "I'd like everyone to turn their attention to my version of the finished 'calculator' applet."
You say, "the URL is: http://boutell.com/~boutell/class/FourCalculator.java"
You say, "now, there are certain unusual things that can happen when working with the caulculator."
You say, "the most important is when the user tries to do something that isn't mathematically possible."
You say, "in particular, division by zero."
You say, "most programming languages handle this by stopping the program dead, right there, rolling over and playing dead."
You say, "now, that wouldn't be very useful if there was no way to avoid it."
You say, "fortunately, there are several ways to avoid it."
You say, "the simplest, at first, is to just make sure you're not dividing by zero before you divide."
You say, "that works, but after a while, you will discover that there are many, many special cases like this in programming."
You say, "after a while, your program doesn't look like a simple recipe any longer..."
You say, "it looks like a rat's nest of special cases to deal with things that hardly ever happen, but are very bad to let go by unchallenged."
You say, "another example, for the calculator, is if the user types in letters instead of numbers and tries to multiply them."
You say, "if we didn't check for that in some way, we would probably get zero, which isn't really the right answer. The right answer is 'you can't do that, that's ridiculous, wake UP, bozo.'"
You say, "again, we could check for this. We could check every character of what's in the 'result' text area to see if it is a legitimate number."
You say, "but it would be nicer to have a way of putting all of this 'special, rare and annoying case' code in one place, out of the way."
You say, "this is what 'exceptions' are all about."
You say, "take a look at the completeOperation() method."
You say, "notice that this method's declaration is different from the others we've seen so far."
You say, "the first line is:"
You say, "void completeOperation() throws BadOperationException"
You say, "would anyone like to take a stab at what this means?"
stevi says, "throw illegal operations to BadOperationException?"
You say, "stevi: that's pretty close, yes."
You say, "stevi: specifically, the 'throws' clause asserts that this method can potentially throw one or more exceptions. This particular method throws the BadOperationException when it sees fit to do so."
You say, "the 'throws' clause is a warning to any method that calls this one: 'you're going to have to be prepared to 'catch' this kind of exception if I throw it.'"
You say, "now, let's skip ahead a couple of lines:"
try {
value = Float.valueOf(text);
} catch (java.lang.NumberFormatException ne) {
BadOperationException oe = new BadOperationException();
throw oe;
}
You say, "sorry for the lack of tabs there. It looks better in the source file."
You say, "would anyone like to guess what this try/catch business is about?"
stevi says, "does that check the number with the NumberFormatException to see if it's legit? then catches the result?"
You say, "stevi: not quite. Nice guess though."
You say, "okay. The method Float.valueOf can potentially throw a NumberFormatException. We know this from looking at the java API documentation."
You say, "Float.valueOf is used to convert a string to a floating point number. If the string doesn't represent a number -- if it contains, let's say, 'BOB SMITH' -- then the exception is thrown."
You say, "if we want to know about that occurrence when it happens, then we 'catch' the exception in a catch clause after the try clause..."
You say, "so: the code in the try { } clause is the stuff we want to do when everything happens in a normal fashion."
You say, "in this case, we want to convert a string to a number."
You say, "the code in the catch { } clause, on the other hand, is what we do when Something Goes Wrong."
gnat says, "what happens if you don't use the try {} stuff, and you give valueOf something that isn't a number in string form? if you give it "booger" will silently give you 0 back? or does the applet stop?"
You say, "gnat: excellent question..."
gnat preens.
You say, "gnat: and the short answer is this: some exceptions stop the applet dead, some don't. The ones that don't mostly have to do with math, including this one. Division by zero with integers stops an applet; with floats it doesn't because a certain spec for engineering geeks says it shouldn't."
You say, "gnat: it is always a pretty good idea to catch exceptions, but to cut you some slack, java doesn't stop your program if you don't catch certain really routine ones having to do with numbers."
You say, "gnat: you may note that we've used Float.valueOf before and gotten away with not catching an exception."
gnat says, "Tom: are the different types of exception built in to java? Or can we make a library card class that can throw "hey, this card is a piece of a cereal box" exception?"
You say, "gnat: look at the top of this applet and I believe you will be enlightened on that question."
stevi says, "so you ought to use try on an operation that could foreseeably go wrong?"
You say, "stevi: yes, exactly. That's just what try is for."
You say, "stevi: and here's a neat thing: you can do lots of potentially bad stuff inside one try { }, as long as you think there's one 'remedy' that's appropriate in the catch { } clause. You don't need a try { } for each potentially scary line."
You say, "stevi: that is why exceptions are less grief, and more elegant, than checking everything at every step."
You say, "clear so far? Should I explain the catch clause a bit more?"
j.j says, "yes, please."
gnat is still hung up on Exceptions.
stevi says, "yes."
You say, "okay:"
You say, "} catch (java.lang.NumberFormatException ne) {"
You say, "notice that there's a variable declaration inside ( ) after the 'catch' keyword."
You say, "this is where we say what class of exception we're catching."
j.j says, "ohhhhhh."
You say, "and if the exception *does* get thrown, we can sometimes do neat stuff with it by looking at the 'ne' variable."
You say, "I'll show you that in a little bit; we don't do it in this particular clause."
You say, "by the way, if you want to catch *all* exceptions, you can say catch (Exception e) and you'll get all of them, because they are all 'extend'ed from Exception ultimately."
j.j says, "where did oe get defined?"
j.j says, "i can't find it."
You say, "j.j: see the next line..."
j.j says, "oh. it's a declaration AND an assignment."
You say, "now, the body of the catch clause:"
j.j says, "i SEE."
You say, "j.j: yes. It is legal to do that. A little verbose, maybe, but it has the virtue that you remember to initialize things."
You say, "BadOperationException oe = new BadOperationException();"
You say, "what we're doing here is *creating* an exception of our very own, so we can throw it."
You say, "we declared that this method could throw exceptions of class BadFormatException..."
You say, "so now, sure enough, we're creating one and 'throwing' it with the throw keyword."
You say, "the moment we do that, a 'catch' clause somewhere else in the program -- where this method was called -- will get activated to cope with it."
You say, "so this is a special way of jumping back pretty far when something bad happens. Sort of like the way you react to touching a hot stove."
You say, "does that make sense?"
j.j nods. "i get it."
stevi says, "i geddit! i geddit!"
You say, "coolness."
gnat says, "if we define our own exception, throw it, and nobody catches it, is there a way to say 'don't stop the program, it didn't really matter anyway?'"
You say, "gnat: the answer to that is 'probably but I haven't sought it out.' You might want to investigate the exception classes in the java.lang package real closely."
You say, "gnat: probably depends on what you derive it from."
gnat thanks Tom and slips him a fiver for his trouble.
You say, "gnat: normally, the *compiler* will stop you if you don't catch most exceptions or declare them in your 'throws' clause for that method. As I mentioned, some of the more routine math exceptions don't stop the program if they are not caught."
You say, "okay..."
You say, "let me just observe that we also check, lower down in this function, to see if the divisor in a division operation is zero. If it is, we throw a BadOperationException the same way."
j.j says, "tom, is checking for division by zero at that point necessary?"
You say, "j.j: technically, dividing by zero is OK for floating point numbers in java; you get a special value, NaN ('not a number')."
j.j says, "our other exception stuff didn't take care of that? no, htat was just for letters, right?"
You say, "j.j: we weren't even dividing at that point; we were just converting a string, yeah."
j.j says, "ok."
You say, "j.j: NaN might be a pretty reasonable thing to print, but I wanted it to act a lot like a traditional pocket calculator."
j.j says, "i see, printing "E" instead."
You say, "yes."
You say, "now, let's go back to the top of the file, and look at the BadOperationException class itself."
class BadOperationException extends Exception
{
String label;
BadOperationException()
{
label = "E";
}
}
You say, "now, when we want to invent an exception of our own, we start by 'extend'ing the Exception class."
You say, "we also need to provide a constructor, as with any class."
You say, "what else we choose to do is entirely up to us. We can provide other methods and member variables if we find them useful."
You say, "for this task, I thought that a 'label' would be a useful thing, since I could then assign a different label in some cases if I wanted."
You say, "I haven't taken much advantage of this, but I might have chosen to write '/0' for division by zero, for example."
You say, "now, let's look at the 'action' method, where the Big Payoff comes."
You say, "in this method, I do different things depending on which button was clicked. We've seen that before. What's new is that the entire thing is inside a big try { } clause."
You say, "notice that, inside that try { } clause, I call completeOperation() in several places."
You say, "now take a look at the catch { } clause..."
} catch (BadOperationException e) {
lastOperation = null;
result.setText(e.label);
}
You say, "here I take care of all those weird, wacky Bad Things that can happen in the same way, in pocket calculator tradition:"
You say, "I forget what was going on before, and I write the label of the exception (an 'E' in this case) on the display."
You say, "now, you can write your calculator perfectly without dealing with exceptions, but they do make it easier. And the bigger your program gets, the more you need them."
You say, "also, many methods built in to the standard java classes throw exceptions, so we will have to catch them often."
You say, "that's the whirlwind tour of exception handling. Questions?"
j.j says, "we have to know we're getting exceptions we didn't specifically call out?"
j.j says, "like, "i'm using this class, it throws an exception, i better catch it?""
j.j says, "that requires omniscience, i think."
stevi throws j.j an exception.
You say, "j.j: yes. But by looking at the java class docs, you can immediately see which methods throw which exceptions. Also, the compiler will stop and tell you if you don't catch 'em."
j.j says, "ok."
You say, "j.j: whether a method throws exceptions is just as basic as whether it returns void or int, what arguments it takes, etc. It is always present in the documentation."
j.j says, "ok."
Tom can go on to some new material, but wants to make sure everyone's cool on this.
stevi's so cool her breath is misting.
j.j says, "i'm ready to go on."
You say, "OK, then: we're going to play with some New Stuff. Specifically, a new applet."
You say, "when we are done with this applet, we'll have at least touched all the important features of the language itself."
You say, "also, we get to play with graphics."
You say, "See: http://boutell.com/~boutell/class/Graph.html"
j.j says, "oooooohhhhhh."
j.j becomes instantly mesmerized.
stevi says, "neat!"
j.j says, "trig refresher course!"
Tom grins.
jkcohen sees the groovy wave.
Tom figgered this group can deal with a teensy bit of math.
Tom figgered j.j would merely laugh disdainfully, in fact.
j.j laughs disdainfully. "ha ha ha."
Tom laughs.
stevi sneaks a peek at the code.
You say, "okay, now click on the source code link."
jkcohen says, "This is about as much math as I can handle."
You say, "hee."
j.j says, "i eat sine waves for lunch!"
You say, "now, let's take a look at the source..."
You say, "the first line imports the awt package. We've seen that before."
You say, "the next line declares our applet class. This is slightly different from the last time."
public class Graph extends java.applet.Applet implements Runnable
You say, "we're extending Applet just as we did last time, but we've got this extra 'implements Runnable' business."
You say, "now, this is a little abstract, but really really important and useful. I'll try to put it simply and skip comparisons to other languages unless asked later."
You say, "in addition to normal classes, java offers a special kind of class called an 'interface.'"
You say, "an interface is a class with no data members -- just methods -- and there's no implementation for the methods, either. Just declarations for them."
You say, "when we say we will 'implement' an interface, we are simply *promising to provide* real versions of those same methods."
You say, "'Runnable' is an interface with just one method: Run()."
You say, "to satisfy the promise we've made, we provide a Run() method later on."
You say, "now, let me explain why we want to do this:"
You say, "when Netscape calls our init() method to set up the applet, the applet has Netscape's full attention. Nothing else can happen until init() returns. It's an awesome responsibility, and all that."
You say, "that's why our init() methods always return pretty fast, and then we do stuff when Netscape alerts us of events."
You say, "but you can see that this applet is animating all the time."
You say, "if we did that in init(), it might work, but nothing else would happen in Netscape. We would be monopolizing the 'thread of execution,' not allowing it to do any other work."
You say, "what we need is our *own* 'thread', to do our own work, independent of Netscape."
You say, "one of the neat, important things about java is that it lets you have your own threads. Lots of 'em, even, if you want."
You say, "there's a Thread class which contains all the methods for working with threads."
You say, "but threads have a problem: where in your program should they start executing?"
You say, "now, anyone care to guess what the Runnable interface is good for?"
j.j says, "telling netscape when to run the thread?"
You say, "j.j: specifically, telling Netscape where the code the thread is going to read is. Telling the thread what to do."
j.j sees the "run()" method now.
You say, "j.j: when you implement the 'Runnable' interface, and then pass your object that implements Runnable to the constructor of Thread, the run() method of your object gets called... and meanwhile the other thread keeps right on going."
jkcohen says, "So it registers the run() method as the method to be invoked as the thread begins execution."
You say, "jkcohen: yes."
You say, "let me run through the init method a little to help clear this up."
You say, "we won't try to cover this entire applet tonight..."
You say, "offscreen = createImage(360, 180);"
You say, "what this does is create an 'image' we can draw on that is not actually on the screen. This is handy so we can draw lots of stuff without the user seeing the paint before it's dry, as it were."
You say, "we use this offscreen drawing area to do messy scribbling and erasing and re-scribbling, and we copy each finished masterwork to the real screen later."
You say, "Graphics g = offscreen.getGraphics();"
You say, "this fetches a 'Graphics' object that can be used to draw on the image. A graphics object is a lot like a paintbrush, associated with some particular canvas."
You say, "we can draw on offscreen images, as well as on the actual screen, with the same methods from the Graphics class."
You say, "clearImage(g);"
You say, "this calls a method a little further down in the applet that actually clears the image. Here's what's in there:"
You say, "g.setColor(Color.black);"
You say, "that sets the paintbrush color to black; the Color class has handy variables like 'black' for a lot of popular colors..."
You say, "g.fillRect(0, 0, 360, 180);"
You say, "that fills a rectangle with its upper left corner at 0, 0, as wide and tall as the entire image."
You say, "so now we've got a nicely erased black canvas to paint on."
You say, "so we're ready for the real action to begin."
You say, "we can't stay in this init() method forever, so we need to create our own thread and return control to Netscape."
You say, "so we create a thread:"
You say, "mainThread = new Thread(this);"
You say, "now, threads don't actually start running until we tell thim to. So now we fire the starting gun:"
You say, "mainThread.start();"
You say, "and we return (to the web browser, so other things can happen in the browser)."
You say, "now the run method starts, in its very own thread, not making everything else wait. Much like another program in Windows or Mac Multifinder or Unix."
You say, "the difference being that this thread shares the same variables, so it can work on the same applet and so on."
You say, "I won't go into detail about it tonight, but the run() method essentially runs in an endless loop, moving a step and drawing on the canvas and repainting and sleeping a little to avoid bogging down other programs."
jkcohen says, "I was wondering about that little nap."
You say, "heh."
You say, "I'm going to stop here to provide time for questions, as we only have ten minutes left."
jkcohen says, "Is the idea of interfaces in Java anything like multiple inheritance in other OO languages?"
You say, "jonathan: yes. There are lots of weird problems with multiple inheritance, but no real worries with interfaces. They turn out to be much simpler and safer and easier to work with."
Tom basks in the apparent omniscience and total comprehension of his class.
j.j is playing with the applet.
You say, "hee."
gnat says, "that would be a 'stunned silence', Tom."
Tom nods.
j.j says, "it's very pretty in yellow."
Tom notes that j.j has figured out the java compiler!
gnat says, "this particular class had some hard things in it."
jkcohen says, "Tom, you have to wait for the concepts to go down the gullet via peristalsis."
Tom nods to gnat. The last class, really, to introduce wholly new features of the language.
gnat says, "Exceptions and Threads in one hour? wow."
You say, "we will talk about threads more next class."
You say, "and in the future no doubt."
j.j says, "tom, if i wanted to add another line with a different period and amplitude in another color would that be a separate thread, or just another Graphic object?"
You say, "j.j: if I were you, I would add the second line by writing two 'drawSomethingStep' methods, and calling them both after the clearing step."
j.j says, "ok."
j.j says, "why can't i set the background block to be blue?"
You say, "j.j: can't you? What's going awry?"
j.j says, "i don't know. maybe it isn't reloading."
You say, "j.j: Netscape won't 'reload' applets very well. Better to use the appletviewer so you can try 'em and trash 'em and try 'em quickly."
j.j laughs.
You say, "j.j: appletviewer accepts a URL, just like a web browser would. It's quite nice."
You say, "If you can't use appletviewer, quit Netscape and restart it. That does work."
jkcohen says, "what does 'synchronized' mean?"
j.j says, "yeah, what the hell is synchronized?"
You say, "okay, 'synchronized' means, 'please don't do something horrible in two threads at once.'"
j.j says, "i don't get it."
You say, "every object has a 'synchronization' lock. When you call a synchronized method, java waits until the lock is free. Then you get the lock until you return."
jkcohen says, "So, in this case, the object is g?"
You say, "jon: in this case, the object is the object the methods belong to. The applet itself."
jkcohen boggles.
You say, "jon: when you say 'synchronized' as part of the declaration of the method, you're saying 'this method waits for any other synchronized method in the same class to finish up before it gets going.'"
You say, "jonathan: a real example to calm you down:"
You say, "jonathan: we draw on our offscreen canvas because we don't want the user to see us erasing and scribbling and so on. It doesn't look good, it's flickery and distracting..."
You say, "jonathan: but it would defeat the purpose if the Netscape thread decided to call paint() on us right when we're busy drawing."
You say, "jonathan: so we make both paint() and drawCurrentStep() synchronized, and the one waits for the other to finish before playing with the offscreen image, and everyone's cool."
You say, "now, I need to stop so I can make a bus. Hee. Thanks for a good class, folks."
Next | Up to the Index
Follow us on Twitter | Contact Us
Copyright 1994-2012 Boutell.Com, Inc. All Rights Reserved.
