Sie sind auf Seite 1von 60

9:00 10:00 11:00 12:00 1:00 2:00 3:00 4:00

About Java Types Gnomes Lunch Break Environment


The Language Variables Threads
OOJ Operations Synchronization
Code Class Decls. Exceptions
Classes Interfaces
Keywords Packages

9:00
Good morning!

Let's Learn Java!


What do you know about Java? Java is part of Indonesia, a nation with more people
than France, England, and Germany put together, located northwest of Australia.
And their history isn't filled with nearly as much stupid infighting as those
Europeans! Java is the most happening island of Indonesia (there are 3 larger islands,
but they don't have as much going on), and the capital Djakarta is the most
happening city on Java. All the major cities are linked with a well developed rail and
highway network, so you can get around just fine. Java is one of the world's most
densely populated areas, and has 35 active volcanos to boot.

Does Java make you think of coffee? Coffee is indeed a major export, along with tea, tobacco,
sugar, coconuts, and cinchona. But the main food crop is rice, along with corn, soybeans,
peanuts, sweet potatoes, and cassava.
Do you equate Java with a cup of coffee? Time to wake up and smell the real Java!
If the next popular programming language is called "England", we'll work to educate you about
that island as well, even though England is relatively boring, having far fewer people, square
miles, and volcanos than Java.

The Java Language


Java is a fairly simple programming language (though it has extensive standard
libraries). A programmer writes .java source files, which get compiled
by javac into .class files containing Java ByteCodes instead of CPU-specific machine
code. The .classfiles are run by a Java virtual machine (interpreter) (e.g. someone's
browser) at run time.

Java programs are just sets of classes.


A Java Applet is a program that is referenced by a web page, and run by a Java interpreter in
your browser when you browse that page.
Any time a class is needed, the browser will load the .class file (probably over the internet) just
once (then it is cached), after which point it can make instances of the class as often as it likes.
An applet is not the main program -- it just responds to various UI (user interface) events, like
the page being loaded by the browser, or a mouse click. Various routines are called when various
events happen, so there are typically many "points of entry" into an applet.
JavaScript is a completely separate language, originally named LiveScript, but renamed to
JavaScript by its creator, Netscape, somewhat early on. You can include JavaScript source code
in an HTML document. We will not discuss JavaScript here. JavaServer Pages (.jsp) are a way
of embedding Java code into HTML-ish pages. We will not discuss JavaServer Pages here
either, although probably we should. [Thanks to Jeff Medina for this info.]

Object-Oriented Jargon (OOJ)


Remember, the purpose of jargon is to separate the "in" people from the "out"
people. Jargon allows you to speak in a special way so that only "in"
people will understand you. It is important to denounce anyone unfamiliar
with the jargon as ignorant and not worth listening to. Proper use of
jargon terms will allow people to identify you as a knowledgable expert,
especially to the extent that they don't understand what you're saying. It
is also important to claim that the jargon enables you to think properly,
and to assume that people unfamiliar with the jargon couldn't possibly
understand the concepts that the jargon enables you to talk about.
In an object-oriented language, functions (subroutines, procedures) are
called methods.
The act of calling (executing) a function is called invoking the method.

A class is a collection of methods, and a collection of variables.

Like a struct in C, or a record in Pascal, the variables exist as a group for every instance of
the class.
Each occurrence of the struct/record (each region of memory which contains a set of the
variables) is called an object.
Wait, didn't we just say it's called an instance? Yes, an object is an instance of its class.
To know the class of the object is to know what struct/record/(set of variables) it has, and what
methods it can perform.
What, how can a set of variables perform anything? Ah, this is the crux of object-oriented
thought. All code is thought of as being executed by some object or another.
Here is some simple Java code:
class Point { // we are defining a class called "Point"
int x, y, z; // it has three integer instance variables
// (every Point instance will have its
// own values for these variables)

// here is a 3-argument function "translate"


void translate(int dx, int dy, int dz) {
x += dx; // this function adds (dx,dy,dz) to (x,y,z)
y += dy;
this.z += dz; // "this.z" is exactly the same as "z"
}
}

Every method in a class has a secret unlisted argument, called this, which is the
group of variables. For example, the above function translate somehow has to
know which point it is translating. The caller must tell it which point to translate. Any
call to translate must be with regard to a specific instance of the Point class.
Point p1; // this says the variable p1 can hold a Point
// but it doesn't hold anything yet (it is null)
p1 = new Point(); // this assigns a newly created point to p1
p1.x = 3;
p1.y = p1.x + 5; // we can work with instance variables like this
p1.z = -4;
p1.translate(2,2,2); // we can invoke the translate method on p1

The last line indicates that when translate is called, the implicit argument this will
be equal to p1.
We say that the point p1 performs the translate method.
If the performer of a method is not specified, it is assumed that thisshould perform
the method, so:
translate(0,3,0);

is the same as:


this.translate(0,3,0);

Of course, this only makes sense (is compilable) if this is a Point.


Class Heierarchy
Classes are arranged in a heierarchy (a tree, to be specific).
When you make a new class, you have to say what it is a subclass of (what
its superclass is).
Object is the class at the top.
Every other class is a subclass of Object, or a subclass of a subclass of Object, or so
on.

A subclass automatically inherits all the variables and methods of its superclass. It may also
define new variables and methods. If it wishes, it can override (redefine) some of the inherited
methods.
Here we define a subclass of Point. We say that we are subclassing Point:
class ColoredPoint extends Point {
int colorNumber;
void changeColor() {
colorNumber++;
}
}

Then we could have code like:


ColoredPoint cp;
cp = new ColoredPoint();
cp.x = 4;
cp.y = 5;
cp.z = 6;
cp.colorNumber = 3;
cp.translate(3,0,0);
cp.changeColor();

Kind Of
We see in the above example that a ColoredPoint is a kind of Point.
And in fact, any subclass of Point (or subclass of subclass of Point, etc.) is a kind of
Point.
An Advanced Topic: Interfaces
Sooner or later (probably later), we will inevitably want to say that a class is a kind of
two different things. For example, a Chair might be a kind of Furniture, and it might
also be a kind of ComfortablePlace. How can we do this?
One way this could be is if Furniture is a subclass of ComfortablePlace,
then Chair could be a subclass of Furniture, and it would then be both a kind
of Furniture and a kind of ComfortablePlace.
But this is conceptually wrong, since we would certainly want to allow other kinds
of Furniture which are not a kind of ComfortablePlace, for example a Shelf. We do
not want to force ComfortablePlace and Furniture to have any particular relation to
each other just because Chair happens to be a kind of both.
Some object oriented languages, like C++, allow multiple inheritance, meaning that a class
can have more than one superclass. Other languages, like Objective C and, in particular, Java, do
not allow multiple inheritance, so we will not discuss it any further!
Java's solution to the problem is the Interface. An interface is like a class, except that it has no
variables. It just has a list of methods, and the methods don't even have any code! An interface
doesn't have any instances. So what good is it?
A class can be declared to implement an interface:
class Chair extends Furniture implements ComfortablePlace {
boolean hasArmrests;
boolean canSwivel;
int legs;
boolean occupied;
boolean occupy() { // return whether occupation attempt succeeds
if (occupied)
return false;
occupied = true;
return true;
}
boolean leave() { // return whether attempt to leave succeeds
occupied = false;
return true;
}
}

Here is what the definition of the ComfortablePlace interface might look like:
interface ComfortablePlace {
boolean occupy(); // return whether attempt succeeds
boolean leave(); // return whether attempt succeeds
}

The compiler, upon seeing that class Chair is declared to implement the
ComfortablePlace interface, will check that this is indeed so.

Now, just as we declared the variable cp above to be of type ColoredPoint, we can declare a
variable to be of type ComfortablePlace. Then the variable is allowed to hold any object that is
of a class implementing ComfortablePlace, and we can invoke any method from
the ComfortablePlace interface:
ComfortablePlace cp;
cp = new Chair();
cp.occupy();

In this way, a Chair is both a kind of Furniture and a kind of ComfortablePlace.


Code
Java code is pretty much nothing but classes. There are no global variables or
precompiler.

Code is written in .java source files (typically one file per class, with the same name as the
class), and compiled into .class class files.

For example, here is a "hello world" program, written as a file HelloWorld.java:


These are like #include statements in C, specifying what libraries (or, more generally, what other classes) will be
used.
They must appear before any class definitions.
import java.applet.Applet;
import java.awt.Graphics;

This says we will define a class called HelloWorld, as a subclass of the already-defined class Applet
public class HelloWorld extends Applet {
Instance variables would go here (or even class variables, indicated with "static"), but we don't happen to have any.
Here we define a method called paint, taking an argument g of type Graphics (that's why we included
java.awt.Graphics above)
public void paint(Graphics g) {
The body of the method is just to call g's drawString method (defined in java.awt.Graphics) with some simple
arguments
g.drawString("Hello world!", 100, 30);
(0,0) is the upper left corner. That starts drawing the string at (100,30).
}
}

To use this applet in a web page, we would use the following html:
<APPLET CODE="HelloWorld.class" WIDTH=200 HEIGHT=30>If this here html is
rendered then your browser can't run applets, perhaps because an option to
enable java is not selected.</APPLET>

This tells the browser that the file "HelloWorld.class" contains a classHelloWorld which must be
a subclass of Applet so that it can respond to all the messages that the browser will send it.
(Applet is in turn a subclass of Panel, then Container, then Component, which can draw and get
events.) We have overridden only the paintmethod.

If you write a Java standalone program (instead of an Applet), then you will use main(), like in
C.
But that's a silly thing to do with Java -- the only real reason to write in Java is to write platform-
independent applets for people to run in their browsers. And for applets, you do not need a
main(). Instead, your Applet subclass (specified in the html) will be sent messages such as
start(), stop(), paint(), etc. These will be discussed at 1:00.

Here is a list of keywords to whet your appetite...


Keywords
abstract type*....................instances not ok, codeless methods ok
boolean type.....................1 bit, true or false (constants)
break flow control......exit switch, loop or labeled block
byte type.....................8 bit signed
case flow control......possibility in a switch
catch flow control......handle a thrown exception
char type.....................16 bit unicode
class type*....................anchor of class declaration
const (unused)
continue flow control......skip remaining code in inner loop
default flow control......catch-all case at end of switch
do flow control......loop: do {code} while (cond);
double type.....................64 bit floating point
else flow control......after if
extends type*....................specify superclass or superinterfaces
final type.....................var: constant, class/method: no subs
finally flow control......code to execute even during exception
float type.....................32 bit floating point
for flow control......loop: for (i=1;i<9;i++) {code}
goto (unused).....................use "break label;" to exit a block
if flow control......branch: if (test) {code} [else {code}]
implements type*....................specify interfaces class adheres to
import compile control...."import java.awt.Graphics;"
instanceof op......."objA instanceof ClassOrInterfaceB"
int type.....................32 bit signed
interface type*....................anchor of interface declaration
long type.....................64 bit signed
native type*....................method body is written in e.g. fortran
new op.......new MyClass(args)inits w/that func
null obj..defined to be unequal to any object
package (type)...scope control...."package mypackage;" marks file
private type.....................visible only within class
protected type.....................visible only to package & subclasses
public type.....................visible to everybody
return flow control......return [a value] from current function
short type.....................16 bit signed
static type.....................specify var or method is "class"
super obj..like "this" but as if in higher class
switch flow control......branch: switch (val) {case 7: code;}
synchronized type.....................only one gnome allowed in at a time
this obj..object the method was called on
throw flow control......abort from code, throwing an exception
throws type*....................specify exceptions method emits
transient(unused).....................not considered part of object's state
try flow control......check for exceptions in a code block
void type.....................the type of 0 bytes of memory
volatile type.....................might be modified asynchronously
while flow control......loop: while (cond) {code}

10:00
This hour we learn the Java language.

Values vs. Variables vs. Types


3 is an integer value. x might be an integer variable, meaning it can hold any integer
value, for example 3. Both 3 and x are of type integer. We often say things like "x is
3", but "is" is misleading -- really, x "holds" 3.

If y is another integer variable, you can't have x hold y. x can only hold an integer value, such as
the value of y. An assignment statement like x=y says that x's value should become what y's
value is.
Some people call variables "lvalues", where the "L" at the front of "lvalue" means that it is
something that can appear on the Left hand side of an assignment. Whether you find this
confusing or clarifying is up to you.
"Automatic" variables are those that are part of some code to execute. This name comes from
how their storage space (on the stack) is automatically created and deleted when the routine is
entered and exited. The only other kind of variable (besides automatic) in Java is an instance (or
class) variable. These terms have to do with scope, not with type.
Types
Java has the following types:
type description
------ -------------------------------------
byte 8 bit signed integer
short 16 bit signed integer
int 32 bit signed integer
long 64 bit signed integer
float 32 bit signed floating point number
double 64 bit signed floating point number
char 16 bit unsigned unicode
boolean one of the two literal values: true or false (not a number)
[name of class or interface]
any object which is a kind of that class or interface
[array type]
any object which is a kind of that
The first eight types listed above (i.e. all but the last two) are called the primitive types,
since they are not defined in terms of anything else -- they are just sequences of bits
that computer cpus are ready to deal with. You are probably already familiar with
types like these, so I won't waste any more words trying to explain them!

Anything that is not a primitive type is a reference type. A reference type is a class, interface, or
array type.
A variable of any reference type may be set to null, meaning that it doesn't hold anything.
(If you are familiar with pointers you will recognize that reference types are pointers to objects.)
The last two types in the table mean that you can use a class or interface name just like you
would use a primitive type. This is pretty neat. Every class is effectively a type. So if myDog is a
variable of type Dog, then any kind of Dog may be assigned to the variable myDog. As another
example, if a variable is of type Object, you can assign any object at all to it.

Dog bigDog = new Dog();


bigDog.fetch(); // This calls the fetch() routine defined in
class Dog
Object anObject = bigDog; // This assignment is ok, since Dog is a kind of
Object
anObject.fetch(); // This is a compile-time error, since fetch()
is
// not defined for Objects
((Dog)anObject).fetch(); // This will work, but if anObject does not
contain a
// kind of Dog when this statement is executed
at
// run-time, then this will generate a
ClassCastException

Even classes themselves are objects, of the class Class, so their type is Class. You don't
normally have to deal with this, but it is reassuring to know that absolutely everything beyond
the primitive types is an object of some class!
There are heaps of "built-in" classes (in the standard libraries), plus of course all the classes you
create.
So there are as many types as you want!
Arrays
The last entry in the table above is for array types. They are represented by having
any of the previous types followed by some number of []'s, one for each dimension
of the array. So Dog[] is an array of Dog's, and int[][][]is a 3D array of ints. Array
types are classes like any other class, and arrays are objects like any other object. For
example, an array has an instance variable length that says how big the array is. So
if mat is a variable of type int[][], then mat.length tells how many int[] rows it has,
and mat[3].lengthgives the length of the third row. The size of a dimension is not a
part of the type. Such sizes are aspects of the values that get assigned.
int[][] mat; // mat === null (mat, as an object, defaults to
null)
mat = new int[2][2]; // mat === {{0,0}, {0,0}}
mat = new int[3][]; // mat === {null, null, null}
mat[0] = new int[4]; // mat === {{0,0,0,0}, null, null}
mat[1] = new int[3]; // mat === {{0,0,0,0}, {0,0,0}, null}
mat[2] = new int[2]; // mat === {{0,0,0,0}, {0,0,0}, {0,0}}
mat[0][2] = 7; // mat === {{0,0,7,0}, {0,0,0}, {0,0}}
mat[3][2] = 4; // throws IndexOutOfBoundsException

If you have an array of type Dog[], then each member of the array can be any kind of Dog.
Dog[] dogList = new Dog[5]; // dogList holds {null, null, null, null,
null}

new Dog[5] creates space to hold 5 dogs -- it creates 5 variables of type Dog. These variables are
each initialized to null until you assign something else to them.

The source code can contain an explicitly typed-out array, but for some reason only in an
initializer:
int[][] mat = {{2,3},{4,5}}; // this is ok
mat = {{6,7},{8,9}}; // but this won't compile!

For some reason, the run-time names of array classes are different from how you specify them in
the source code -- an array of ints is int[] in the source code but "[I" at run time. I can't
imagine why this is.
A Very Subtle Point:
If you have a variable dogList of type Dog[], then you can also assign dogListto be an array of
type SeeingEyeDog[]assuming SeeingEyeDog is a kind of Dog. But then you need to be careful
that you won't be hit by the following potential run-time problem: If you say dogList[3] =
stupidDog (which looks fine to the compiler as long as stupidDog is a kind of Dog),
an ArrayStoreException can be thrown, since an array of type SeeingEyeDog[]cannot
contain stupidDog if stupidDog is not a kind of SeeingEyeDog.
Initialization
Objects are always initialized to nullunless they are explicitly initialized otherwise.
Primitive-type variables fall into two categories: Automatic ones must be initialized
before use. Instance (or class) ones are automatically initialized to 0 or false.
If an automatic variable is not initialized before it is used, that is a compile-time error. Here's
how the compiler decides whether something is initialized:
Change all values (except for boolean constant expressions) to "blah". Then, see if
you can still tell that the variable must necessarily have been assigned, considering
just the possible flows of control (including boolean-switched evaluation
like &&, ||, ?...:). Also, consider try statements to be capable of immediately
throwing any exception.

int b; | | int b;
while (3>5) { | | while (false) {
b = 3; | | b = blah;
} | | }
foo(b); | | blah(b); // b not initialized
| |
int c; | | int c;
if (flag) | | if (blah)
c = 14; | | c = blah;
else | | else
c = 17; | | c = blah;
foo(c); | | blah(c); // c is initialized
| |
int d; | | int d;
if (flag) | | if (blah)
d = 20; | | d = blah;
if (!flag) | | if (blah)
d = 30; | becomes | d = blah;
foo(d); | | blah(d); // d not initialized!
| |
int e; | | int e;
if (flag || !flag) | | if (blah || blah)
e = 5; | | e = blah;
if (flag && !flag) | | if (blah && blah)
foo(e); | | blah(e); // e not initialized!
| |
boolean f; | | boolean f;
if (flag && (f=true)) | | if (blah && (f=true))
foo(f); | | blah(f); // f is initialized
| |
boolean g; | | boolean g;
if (flag || (g=true)) | | if (blah || (g=true))
foo(g); | | blah(g); // g not initialized
| |
int t; | | int t;
try { | | try {
t = 5; | | t = blah;
foo(t); | | blah(t); // t is initialized
throw(new MyException()); | | throw(blah);
} catch (MyException e) { | | } catch (blah) {
foo(t); | | blah(t); // t not initialized!
} | | }

Classes
For convenience, there are classes corresponding to each of the primitive types.
For example, the Integer class has a constructor to make an integer from a string, and
an intValue() method that returns an int:
if (getParameter("side") != null)
side = (new Integer(getParameter("side"))).intValue();
Strings
Strings are totally objects, members of the class String. They are not arrays of
characters like in C. If the source code contains "hello", it will be compiled as a String
object.
int theLen = "A String".length();
The + operator concatenates strings, promoting first if necessary.
x = "a" + 4 + "c"
is compiled to the equivalent of:
x = new StringBuffer().append("a").append(4).append("c").toString()
I don't know whether "value = "+3+4 is supposed to result in "value = 34" or "value =
7".
(Note that in Java, the "just try it and see" method can lead to big trouble: Perhaps
the Java specification does not specify the answer, in which case you will of course find
some answer when you try it and see on your computer, but then when you write
code based on what you learned, your code won't work on other people's
computers, which have different Java implementations.)
You can't mess with the contents of a String. If you want to, use a StringBuffer
instead.
Variable Scope
A variable's scope is from its declaration to the end of the block it is declared in.
The declaration need not be at the beginning of a block:
for (int i = 1; i < 10; i++)
But you can't declare after a comma, so you can't do:
for (int i = 1, byte j = 10; i < 10; i++, j--) // WON'T COMPILE!
What's really going on in that example? The first "int" means that everything up to
the next ; is a declaration. But the next ; also delineates the next part of the for. So
the whole first part must be an int declaration.
But even the following is no good:
int i;
for (i = 1, byte j = 10; i < 10; i++, j--) // WON'T COMPILE!
If it's so hard to declare in for loops, I don't see why it's allowed at all.
Here's the answer: Java has a hack that lets the initialization of a for loop (but no
other weird place) be an initializer. This means that it starts with a type, and then as
many variables as you want of that one type, each initialized if you wish. So you cando:
for (int i = 1, j = 10; i < 10; i++, j--) // compiles ok

Note that if you declare a variable inside a loop, then it is undefined for the part of the loop prior
to its declaration, and its initialization, if any, will be performed for every pass of the loop.
Operations
Java basically has all the same operators as C, but + can concatenate strings,
and >>> shifts right filling with zero (not the sign bit).
Floating point values as well as integer values can be incremented and decremented
with ++ and --.
For boolean values, & and && are the same except that && won't evaluate its second
argument if the first argument was false. Or'ing is similar.
Floating point operations never produce exceptions (they can produce NaN though),
and integer operations only generate an ArithmeticException upon /0 or %0.
A boolean can't be cast to or from anything else.
Casts between different integer types either drop bits (to shrink) or extend the sign
bit (to grow).
Casts involving floating point numbers always result in the representable value
closest to the original value, except: If the final type is less than 32 bits, first it
converts to a 32-bit integer, and then it chops off bits. In particular, very large (or
infinite) positive values become -1 and large negative values become 0!
If NaN is cast to an integer, it becomes 0.
[[prioritized list of ops]]

Control Flow
Very simple. Same as C. Hope you know C!
There are only a couple of differences: exceptions, labeled break/continue, and no
goto.

Labeled Break and Continue


A block or statement can have a label, say foo:{some code}. Then, if, inside the labeled part,
a break foo; is encountered, the labeled section will immediately be exited. If a continue
foo; is encountered, the labeled part (which must be a for, do, or whilestatement) will
immediately be continued.

Method Declaration
[accessSpecifier] [static] [abstract] [final]
[native] [synchronized] returnType methodName ([paramlist])
[throws exceptionsList]

static means the method is a class method -- it may be invoked by ClassName.methodName as


well as instance.methodName (there is no difference -- use whichever is handier).
A static method therefore cannot use instance variables, or this, since there may not even be any
instance in existence!
abstract means the method has no code -- a subclass must override (redefine) the method,
supplying code. In this case, the declaration is followed by a semicolon instead of code.
final is the opposite of abstract -- it means that subclasses are not allowed to override the
method.
native means the the code for the method is written in some language other than java. We will
not discuss this sort of weirdness.
The return type may be a type, or void. If the return type is void, then no value is returned. No
return statement is needed, and if there is one (for example to return from a point other than the
end of the function's code), it must omit the value. (It may not even specify a "void" value,
e.g. return voidFunction(3,5); is not allowed.)
Variable Declaration
Instance variables are declared in a class definition like this:
[accessSpecifier] [static] [final]
[transient] [volatile] type varName [= init];

static means the variable is a class variable -- there is only one copy of this variable, no matter
how many instances exist. Instances do not have their own copy of this variable -- they all share
the one unique copy.
The variable may be referenced as ClassName.varName as well as instance.varName (there is
no difference -- use whichever is handier).
final means that the value of the variable, specified by the init at the end of the declaration,
will never change. This means the compiler can treat it as a constant, rather than creating storage
for it, and perhaps make other optimizations as well.
transient means that the variable should not be considered part of the object when the object is
being archived. What does this mean? Who knows. Current versions of Java all ignore this
anyway!
volatile means that the variable can be changed asynchronously, and the compiler should
specifically avoid optimizations that assume the variable's value to be, say, the same as what it
was the last time you looked.
The init is executed when a new instance is created (or when the class is created, if static),
prior to the execution of the constructor.
Access Specifiers
Access specifiers are to help make code modular and reusable, by clearly specifying
the scope of a class, class variable, or method.
Small programs can ignore them for the most part, but packages should use them
carefully.

There are four scope levels that can be specified:


private | package | protected | public

A class's code can always access member variables of objects of that class -- but if the
variable is private, then nothing else can see it, even within the package.
A package variable (the default -- there's no need to explicitly specify this) is visible
only within the package.
A protected variable is also visible to subclasses outside the package, but only for
objects of those subclasses. (why???)
And finally, a public variable is accessible by code anywhere.

Are these compile-time or run-time restrictions? Run-time!


That is, at run time you can ask what methods a class implements, and so on.
"Static" variables or methods are class variables and methods.

What does a public method mean for a non-public class?


For example, interface methods must be public. But why, if the interface isn't public?
An abstract method may only appear in an abstract class.
You can't have an abstract static method. Why?
All methods in a final class are automatically final. The same is true for private methods.
If a method is static and has no type or name, then it is init code for the class.
Why can't a constructor be synchronized (or anything else)?
Interfaces
An interface is like a protocol in Objective C. But anyway...
An interface is a list of methods and constants.
A class "implements" the interface if it implements all of the methods in the list.

You declare an interface like this:


[public] interface Pokable [extends Botherable, Malleable] {
int JAB = 8, TICKLE = 3;
void pokeMe(PokerObject poker);
boolean beenPoked(void);
}

If "public" is present, then the interface will be available outside the package.
Extended interfaces can have methods or constants hidden by the new interface.
All the methods are automatically "public abstract".
All the constants are automatically "public static final".
class Pig extends LiveStock implements Pokable, Feedable {
void PokeMe(PokerObject poker) {
}
void FeedMe(FoodObject feed) {
}
boolean beenPoked(void) {
return true;
}
}

Interfaces may be used as variable types!

Class Declaration
[public] [abstract | final] class ClassName [extends SuperClassName]
[implements InterfaceName1 [,InterfaceName2]...]
{
in any order:
instance vars (class vars marked by "static")
(these can shadow inherited vars! "super." may help, or may
not...)
instance methods (class methods marked by "static")
(same goes here)
static {init code that gets executed when class is loaded}
}
If you don't specify a superclass, "Object" is assumed.
Public classes must appear in a file with the same name as the class. Why?

Constructors
super(arg1,arg2); executes the superclass's (relative to the class of the method in
which it appears) appropriate constructor method.

new Point(3) creates and returns a new instance of the Point class.
It's code sets this.x, this.y, or whatever it needs to. It behaves syntactically as if it is type void.
The method Point(int n) is a "constructor" because it has the same name as its class -- it gets
called automatically (by "new") after the instance has been created, to give the instance a chance
to do some automatic initialization of its state. There can be different constructors (distinguished
by taking different numbers or types of arguments).
How can one constructor call another (to avoid duplicating initialization code)?
The first line of a constructor may be this(args); or super(args);, indicating that another
constructor should be executed before the remainder of the body of this constructor is executed.
If there is no such first line, then super(); is assumed.
If no constructor is supplied, then one with no arguments, calling super(), is assumed.
The method finalize() is a "destructor" because its name is "finalize" -- it gets called
automatically by the garbage collector just before the instance is destroyed, to give the instance a
chance to do some automatic "finalization" (the opposite of "initialization"), such as closing
streams. It should probably end with
super.finalize();

Packages
Libraries (collections of functions) are called "packages" in Java.

After you understand the syntax and semantics of the Java language, the main thing you will
spend time learning about is the large set of classes that are a standard part of Java. You will
learn about classes that enable you to get input, produce output, and do countless other things.
These classes are supplied as packages.
You can make a package like this:
package graphics; // applies to this whole file

interface Draggable {
. . .
}
class Circle {
. . .
}

class Rectangle {
. . .
}

All files containing the package graphics line will be considered to be in


your graphics package.
That line must be the first one in the file???
The resulting .class files must be placed in a "graphics" directory on the CLASSPATH.
The package name can have internal period-separators.
If you don't specify a package, you are in the "default package", which is always imported.
Remember that only public methods and interfaces are visible outside the package.
You can import by:
import graphics.Circle;
or
import graphics.*;

What does import really mean???

If the same class is in two packages you have imported, you can specify which class you intend
by prepending the package name to the class name:
graphics.Circle

11:00
You want to do several things at once?
Or stop suddenly but gracefully?
This hour we'll learn about two different things:
Threads, and Exceptions
The concepts needed for thinking about these are introduced,
since you can't avoid dealing with these in Java,
and Java's mechanisms for dealing with them are shown.

Gnomes
Normally, in your program, there is a flow of control. You can tell the flow how to go
by calling functions, using loops, etc. It is like there is one little bustling gnome, being
told what to do as it goes from line to line of your code.
A natural idea, especially when you want your program to do two unrelated activities, is to let
there be more than one gnome. Each gnome can then follow code around, line by line. Of course,
you will need to take care that they aren't each messing with variables that the other is using --
that would cause a lot of confusion for the poor gnomes, and their algorithms would be ruined!
All the object-oriented metaphors talk about the "object" performing the activities described in
its methods. Don't be fooled! Gnomes do the work. For example, one object can do two things at
once, if two gnomes are executing its code. If an object doesn't have any gnomes doing work for
it (and this is usually the case for most objects, since there are typically many more objects than
gnomes), then it can't do anything at all until a gnome arrives on the scene. And in fact, the
gnome manipulates the object, not the other way around. The only "control" the object has over
anything is that in some sense the code represents the will of the object. A method is something
that the object might be asked to do. The code for the method represents how that kind of object
chooses to respond to that request, and it is executed by any gnome that is sent to that method.
Objects never get to do anything except respond to requests and messages. (Often the requests
are actually sent from the object to itself. For example, an object that is asked to go to the next
room might first ask itself to stand up, and then ask itself to walk in a certain direction.) "Being
asked to do something" means that a gnome is sent to the object's method for responding to that
request. When the gnome is done handling a request, it returns to the higher-level request that it
had previously been working on. The object-oriented jargon talks about a "method" being
"invoked" or a "message" being sent. Really, a gnome is sent. Sometimes the gnome is sent with
a message, and sometimes it is sent with a request. The only difference is in your mind. A gnome
always arrives just to perform a specific method, and when it is done, it leaves. They have an
incredibly strong work ethic.
Threads
Computer gnomes wear rather threadbare clothes compared to their cousins in the
forest, and so the unfortunate slang term "thread" arose for these gnomes. However,
their hard work has earned this term a lot of respect, and now they even call
themselves "threads" with pride!

In Java, each gnome (each thread) has a Thread object associated with it. This object stores the
name of the thread, along with any other knick-knacks a thread might desire. The thread itself is
just running around mindlessly executing code, and has no memory or sense of self. Actually,
that's not quite true. It has its own call stack, where it keeps passed arguments, local variables,
and return values. And it knows where its Thread object is. That is where it stores its name and
so on. This can come in handy for example if you have different instructions for different threads
(you would have instructions like "if your name is Sam, do such and such").
Thread.currentThread() is an introspective class method -- if you send a gnome off to execute
this method, then it will come back with its associated Thread object.
new Thread(name) creates a new soulless instance of the Thread class, a "missing gnome" file.
If a gnome X executes the start() method for a "missing gnome" object, then the "missing
gnome" comes into being as a real live gnome Y, and Y runs off to execute its run() method. The
original gnome X just returns to its caller, without worrying about what the new gnome is up to.
If the new gnome Y ever returns from the run() method, it is automatically and painlessly
terminated.
When Y comes into being, it looks for its run() method. It may have one itself, if it is a subclass
of Thread that has a run() method. But it might not have one -- then it looks for a run() method
of its "target" object. What is its target?
new Thread(obj,name) makes a new instance of the Thread class, which has obj as its "target".
The class of obj should implement Runnable (have a run() method).
There are various methods of the Thread object that control the activity of the associated gnome:
(I think they all also exist as class methods, operating on the gnome that executes them.)
The stop() method immediately and painlessly terminates the gnome (by
throwing a ThreadDeath error exception at it!). If the gnome had not yet been
created (i.e. it was a "missing gnome"), it doesn't matter -- it is quite dead after
this, and has no chance at life. This is an asynchronous death, so for gnomes
that could leave things in a disordered state, it is better to set some flag that
they can check at a safe time, killing themselves if they find it set.

The sleep() method causes the gnome to immediately fall asleep for the
specified number of milliseconds. When it wakes up, it will continue where it
left off.
The suspend() method puts it to sleep until someone else executes its resume()
method.
If the thread calls wait(), then it sleeps until that thing calls notify() or
notifyAll().
If a gnome is supposed to do some I/O on a device that is busy, it will fall
asleep until the device is free. This is probably implemented with the above
strategies.
You can setPriority(p) with Thread.MIN_PRIORITY <= p <= Thread.MAX_PRIORITY
or setDaemon(true) (interpreter will exit when only daemon threads remain).
Synchronization
Sometimes there might be different gnomes that need to work with the same data.
They can't both work on the data at the same time, or terrible things could happen:
Gnome 1 Gnome 2
------------------------- -------------------------
pick up the scissors
pick up the scissors
put fabric 2 in scissors
position fabric correctly
put fabric 1 in scissors
cut fabric
position fabric correctly
put fabric down
cut fabric
put fabric down
Here each gnome is doing something that by itself seems sensible. But at the same
time, another gnome is messing around with the same scissors, and the result is
disaster! Gnome 2 is cutting the wrong fabric in the wrong place, and Gnome 1 winds
up snipping thin air! This just goes to show how brainless threads are. They are so
busy working that they never look up to see if what they're doing makes any sense.

People usually solve this in the following way: Whoever gets to the scissors first gets to use them
until they are done, at which point they give the scissors to the other person, who had to idly wait
until they got the scissors.
From an object-oriented point of view, we might have an object theScissors, with a method
cutFabric(). To solve the problem of thread brainlessness, theScissors would know that there are
certain activities that are only safe for one gnome to do at a time, such as cutting fabric. Such
activities (methods) are marked with the keyword "synchronized". Any time any thread wants to
start executing synchronized code, it will first make sure no one else is doing so for that object. If
someone else is doing so, it has to wait its turn. But once it is executing the synchronized code, it
can be sure nobody else will do so until it has finished.
The way this works is that there is a solid gold baby monitor excavated from the tomb of
Cheops. This item is popular with objects, but since the real article is in the London museum,
each object just has a little gold-tone plastic replica. There is a bizarre tradition dictating that
gnomes may only enter "synchronized" code if they have the object's baby monitor. Only one
gnome can have the monitor at a time, so if a gnome enters synchronized code on behalf of a
certain object, no other gnomes may do so until it has finished with the synchronized code, thus
relinquishing the monitor.
synchronized (myObject) {code executed when myObject's monitor is obtained}
wait() -- sleep until notified (letting go of monitor)

notify(), notifyAll() -- wake up all waiters.


These can only be called when you have the monitor -- why???
Are constructors automatically synchronized? The docs say it can't matter, since nothing else
can see the object before the constructor finishes. That doesn't seem right, though. ???

Exceptions
try {code that might throw exceptions}
catch (MyThrowable var1) {...}
catch (Throwable var) {...}
finally {...}
If an Error or Exception is thrown, then the first (if any) applicable catch is executed.
In any event, the finally block is executed, even if the remainder of the function will
be skipped due to an active exception..

Here's how to indicate that your routine may emit a throwable instead of its return value:
public void writeList throws IOException, ArrayIndexOutOfBoundsException
{...}
Here's how things are thrown:
throw aThrowable;
Runtime exceptions can happen from any function -- functions do not need to
declare that they might throw them.
Examples are 1/0, null.x, a[-3], etc.

There are two built-in kinds of Throwable:

 Error, for bad conditions that one is not expected to recover from

(an error in the runtime system, or in a dynamically loaded class file, or a


ThreadDeath)
 Exception, for trip-ups that a program should be able to recover from

(mostly IO -- things the code might hope won't happen, but can't tell in
advance)
o RuntimeException, for when a program goofs up

(in arithmetic, using arrays, etc. -- things a careful code-examiner could


have predicted)
Exceptions that are not RuntimeExceptions, therefore, are trip-ups that a program
should be ready for, such as file-not-found when trying to open a file, etc.

Let's consider the FileNotFoundException. You might think that a careful program could first
check to make sure the file exists, and only open it if it exists. But even this is not 100% safe --
another program could delete the file after you checked that it exists, but before you opened it.
The only way to really tell whether you can open it is to just try, and see whether you succeed or
fail. In Java, failure is indicated by an exception being thrown.
As such, the compiler requires that such exceptions be specified in the function declaration if
they might be thrown by the function. So if you have a function that opens a file, and it doesn't
bother to catch the file-not-found exception, then the exception will be thrown to the calling
function -- the function declaration must specify this, so that callers know to expect the
exception.

12:00
Lunch Break
You are done learning the language.
Hungry? Go eat lunch.

1:00
You want interactive buttons and pictures?
This hour we will learn about GUI stuff.

The Java Run-Time Environment


Java's environment is essentially Yet Another Windowing Narcissism.

Instead of a simpler GUI model, we are faced with yet another windowing system whose
complexity is comparable to previous windowing systems. That is, it is a huge bureaucracy of
events, drawing commands, and so on.
AWT == Abstract Windowing Toolkit
We will try to separate the bureaucracies from each other to simplify the picture.

 Coming into (and out of) existence as an application or applet


o Housing bureaucracy
o Thread bureaucracy
o Parameter bureaucracy
 Receiving gui input and notifications
o Event bureaucracy
o Button, slider, etc. bureaucracy
 Producing gui output
o Container and layout bureaucracy
o Drawing bureaucracy
o Image bureaucracy
o Sound bureaucracy
 Communicating with other programs or the host machine
o Browser bureaucracy
o Inter-applet bureaucracy
o Security bureaucracy
o System bureaucracy

Housing Bureaucracy
The browser sends the applet various messages in relation to giving it a home or a
job.

import java.applet.Applet;

 public void init() - called when applet is loaded -- better to do initialization


here than in the constructor, since much of the support (for example the
ability to load images) has not yet been constructed at applet construction
time.
 public void start() - called when page gets shown
 public void stop() - called when page disappears
 public void destroy() - called when applet is unloaded (when would this
happen???)
Thread Bureaucracy
 notifyAll -- a synchronized method -- wakes up threads waiting for the monitor
 notify -- a version that wakes up only one thread at random (when is this
good???)
 wait -- in synchronized code -- go to sleep until woken up, relinquishing
monitor in the meantime
 wait(long timeout) -- only nap for timout milliseconds
Parameter Bureaucracy
Parameters inside the <applet ...> tag are for the browser to be able to run the
applet.
Parameters between <applet ...> and </applet> are like command-line arguments to
the applet.
<Applet
Code="MyApplet.class"
Width=200
Height=100
CodeBase="http://myco.com/~mysource/"
Alt="Your browser understands APPLET but can't run applets."
Name="instance 5"
Align=top
VSpace=10
HSpace=20
>
<Param Name=InnerMethod Value="3">
<Param Name=OuterMethod Value="bubbling">
Html to appear in browsers that don't understand the APPLET tag.
</Applet>

The first three (code, width, height) are required. The rest are not. The order doesn't matter.
The last three are the same as for the IMG tag. The html keywords are all case-insensitive.
"Codebase" lets you specify an absolute url. (The default is the url of the html page.) The
"code" file must be relative to this, not absolute.
In the "param" tag, the "value" field is always passed to the applet as a string, regardless of
whether quotes are used.
The java code can read a parameter like this:
String outerMethod = myApplet.getParameter("OuterMethod");
This will return null if there is no such parameter supplied!
This must be done in the applet's init() or later -- doing it in the constructor fails badly.
You can get values of parameters inside the APPLET tag in just the same way.
Methods such as Integer.parseInt (throws NumberFormatException) can be useful for turning the
string into a preferred type.
Extremely interactive environments will be able to show a page writer the following information
if you supply this method in your applet subclass:
public String[][] getParameterInfo() {
String[][] info = {
// Parameter Name Kind of Value Description
{"InnerMethod", "int", "number of approximations to
make"},
{"OuterMethod", "activity", "bubbling, snorting, or
whizzing"}};
return info;
}

Event Bureaucracy
Events have changed with Java 1.1. But my Netscape 4 can only handle the old style,
so that's what I discuss.

Events are passed up the container heierarchy by default.


You can look at, alter, or stop an event before it continues up the heierarchy.
An event arrives at a component in the handleEvent() method, which dispatches the event to the
appropriate handler according to its type. If you override this, you probably want to return
super.handleEvent to take care of the dispatching (e.g. otherwise action events can't get
generated).
import java.awt.Event;

 action() // sent by buttons, etc.


 mouseEnter(), mouseExit(), mouseMove(), mouseDown(), mouseDrag(),
mouseUp()
 keyDown(), keyUp()
 gotFocus(), lostFocus
These are public boolean functions that return true if the event should stop going up
the container heierarchy.
An Event e has a type, target, timestamp, location, keyPressed, data, modifierKeys.
e.type
Button, slider, etc. bureaucracy
These classes are java.awt.gizmoname, where gizmoname is one of:
Button, Checkbox, TextField, TextArea, Label, List, Choice, Scrollbar, Canvas, Menu,
MenuItem, CheckboxMenuItem, Panel, Window, etc.
An object containing such a control will have its action() method called if the control
receives an event.
Container and Layout Bureaucracy
 add
 remove
 setLayout
 validate -- creates peers for all the contents (done automatically if about to be
shown for first time), causing them to be drawn
 GridBagLayout
 BorderLayout
Outer components are drawn, then inner ones (ones they contain) (in no particular
order).
Every component must be in a container if it wants to be shown.
A Container is a kind of Component.
The only exception is the top-level container -- a Window.
There are two kinds of Windows: A Frame is a first-class window, while a Dialog is a
subsidiary window.
A Panel groups things together in part of a display area.
A Container uses a LayoutManager to control the layout of its stuff.
What is a LayoutManager?
Every
There are several pre-supplied layout managers, or you can write your own.

Drawing bureaucracy
import java.awt.Graphics;

 public void paint(Graphics g) - draw yourself - default does nothing - executed


by the AWT's inimitable drawing gnome
 update(Graphics g) -- executed by the drawing gnome - default draws a gray
rectangle and calls paint() - this sequence can lead to "flashing"
 repaint() -- puts update() in the drawing gnome's queue of things to get
around to - can specify a subrect to be painted
The drawing gnome sometimes calls paint() directly, e.g. if the window gets
uncovered.
You could put the drawing commands in update() and have paint() call update() if you
wanted.
But why is there both an update() method and a paint() method?
"Double buffering" is just drawing into an image, and then painting by copying the image. See
Image Bureaucracy.
A Graphics object represents a drawing context, and lets you draw empty/filled rectangles, arcs,
lines, ovals, polygons, text, and images. The following examples operate on graphics object g.
Coordinates are in pixels, with y increasing as it goes down.

 g.drawLine(ax, ay, bx, by);


If you want to draw just a single pixel, you have to do something silly like
drawLine(x,y,x,y).
The following drawing commands all also have a "fill" version, starting with "fill"
instead of "draw".
 g.drawRect(minX, minY, width, height);
 g.draw3DRect(minX, minY, width, height, isRaised);
 g.drawRoundRect(minX, minY, width, height, arcWidth, arcHeight);
 g.drawOval(minX, minY, width, height);
 g.drawArc(minX, minY, width, height, startAngle, endAngle);
 g.drawPolygon(polygon);
To make a polygon, use "new Polygon", and then addPoint(x,y) to it repeatedly.
drawPolygon doesn't close the polygon, but fillPolygon does, and uses even/odd fill.
 g.drawString("Hello World!", minX, baselineY);
 g.drawImage(
The drawing color is initially the Component's foreground color. "Clearing" color is
Component's background color.
The Graphics object also lets you get/set color, font, clipping area, paint mode

Image bureaucracy
 getImage
Here's an example of how to do "double buffering":
Dimension dbDims; Image dbImage; Graphics dbGraphics;
if (dbGraphics == null || d.width != offDimension.width
|| d.height != offDimension.height) {
dbDimension = d;
dbImage = createImage(d.width, d.height);
dbGraphics = dbImage.getGraphics();
}
// draw into our image
dbGraphics.setColor(getBackground());
dbGraphics.fillRect(0, 0, d.width, d.height);
dbGraphics.setColor(Color.black);
dbGraphics.fillRect(x, y, w, h);
// copy the image to the screen
g.drawImage(dbImage, 0, 0, this);
Even the init is in the update() method because until then we don't know what size we are.

Sound bureaucracy
 getAudioClip(URL [,string] ) -- returns an object that implements AudioClip
 play -- same as above but plays it
 AudioClip interface: loop, play (once), stop (immediately)
Browser bureaucracy
 showStatus("MyApplet: Loading image file " + file);
 standard output and error sent to java console in netscape.
 System.out.println("Called someMethod(" + x + "," + y + ")"); // can use err as
well as out
 tell browser to show URL: public void showDocument(java.net.URL url [, String
targetWindow] )
 targetWindow can be: "_blank" (new window), [windowName] (maybe new),
"_self" (applet's window & frame), "_parent" (one frame up from applet),
"_top" (highest frame in applet's window)
Inter-applet bureaucracy
 you can invoke public methods of other applets on the same page
 the java.net package lets you communicate with programs running on the
machine
 String host = getCodeBase().getHost(); // tells what host the applet came from
 you can use sockets and a demon on the applet source's machine to enable
communication between multiple viewers
Security bureaucracy
System Bureaucracy
 String s = System.getProperty("os.name");
 file.separator, java.class.version, java.vendor, java.vendor.url, java.version,
line.separator, os.arch, os.name, path.separator

doc bugs:
sun:
of course sound creation returns immediately -- it is specified to do so -- sound only
loaded when played
lang spec:
atan2 has arguments in other order

stupidities:
flow control not improved -- it's still a pain to decide whether every linked list in a square array
contains a predator
interface methods must be public, so the compliant methods must be public,
so a public class is forced to expose interface-related methods regardless of whether they should
be visible outside the package
9:00 10:00 11:00 12:00 1:00 2:00 3:00 4:00
About Java Types Gnomes Lunch Break Environment
The Language Variables Threads
OOJ Operations Synchronization
Code Class Decls. Exceptions
Classes Interfaces
Keywords Packages

9:00
Good morning!

Let's Learn Java!


What do you know about Java? Java is part of Indonesia, a nation with more people
than France, England, and Germany put together, located northwest of Australia. And
their history isn't filled with nearly as much stupid infighting as those Europeans!
Java is the most happening island of Indonesia (there are 3 larger islands, but they
don't have as much going on), and the capital Djakarta is the most happening city on
Java. All the major cities are linked with a well developed rail and highway network,
so you can get around just fine. Java is one of the world's most densely populated
areas, and has 35 active volcanos to boot.

Does Java make you think of coffee? Coffee is indeed a major export, along with tea, tobacco,
sugar, coconuts, and cinchona. But the main food crop is rice, along with corn, soybeans,
peanuts, sweet potatoes, and cassava.
Do you equate Java with a cup of coffee? Time to wake up and smell the real Java!
If the next popular programming language is called "England", we'll work to educate you about
that island as well, even though England is relatively boring, having far fewer people, square
miles, and volcanos than Java.

The Java Language


Java is a fairly simple programming language (though it has extensive standard
libraries). A programmer writes .java source files, which get compiled
by javac into .class files containing Java ByteCodes instead of CPU-specific
machine code. The .classfiles are run by a Java virtual machine (interpreter) (e.g.
someone's browser) at run time.

Java programs are just sets of classes.


A Java Applet is a program that is referenced by a web page, and run by a Java interpreter in
your browser when you browse that page.
Any time a class is needed, the browser will load the .class file (probably over the internet) just
once (then it is cached), after which point it can make instances of the class as often as it likes.
An applet is not the main program -- it just responds to various UI (user interface) events, like
the page being loaded by the browser, or a mouse click. Various routines are called when various
events happen, so there are typically many "points of entry" into an applet.
JavaScript is a completely separate language, originally named LiveScript, but renamed to
JavaScript by its creator, Netscape, somewhat early on. You can include JavaScript source code
in an HTML document. We will not discuss JavaScript here. JavaServer Pages (.jsp) are a way
of embedding Java code into HTML-ish pages. We will not discuss JavaServer Pages here
either, although probably we should. [Thanks to Jeff Medina for this info.]

Object-Oriented Jargon (OOJ)


Remember, the purpose of jargon is to separate the "in" people from the "out" people. Jargon allows you to speak in a special way so that only
"in" people will understand you. It is important to denounce anyone unfamiliar with the jargon as ignorant and not worth listening to. Proper use
of jargon terms will allow people to identify you as a knowledgable expert, especially to the extent that they don't understand what you're saying.
It is also important to claim that the jargon enables you to think properly, and to assume that people unfamiliar with the jargon couldn't possibly
understand the concepts that the jargon enables you to talk about.
In an object-oriented language, functions (subroutines, procedures) are
called methods.
The act of calling (executing) a function is called invoking the method.

A class is a collection of methods, and a collection of variables.

Like a struct in C, or a record in Pascal, the variables exist as a group for every instance of
the class.
Each occurrence of the struct/record (each region of memory which contains a set of the
variables) is called an object.
Wait, didn't we just say it's called an instance? Yes, an object is an instance of its class.
To know the class of the object is to know what struct/record/(set of variables) it has, and what
methods it can perform.
What, how can a set of variables perform anything? Ah, this is the crux of object-oriented
thought. All code is thought of as being executed by some object or another.
Here is some simple Java code:

class Point { // we are defining a class called "Point"


int x, y, z; // it has three integer instance variables
// (every Point instance will have its
// own values for these variables)

// here is a 3-argument function "translate"


void translate(int dx, int dy, int dz) {
x += dx; // this function adds (dx,dy,dz) to (x,y,z)
y += dy;
this.z += dz; // "this.z" is exactly the same as "z"
}
}

Every method in a class has a secret unlisted argument, called this, which is the group
of variables. For example, the above function translate somehow has to
know which point it is translating. The caller must tell it which point to translate. Any
call to translate must be with regard to a specific instance of the Point class.
Point p1; // this says the variable p1 can hold a
Point
// but it doesn't hold anything yet (it
is null)
p1 = new Point(); // this assigns a newly created point to
p1
p1.x = 3;
p1.y = p1.x + 5; // we can work with instance variables
like this
p1.z = -4;
p1.translate(2,2,2); // we can invoke the translate method
on p1

The last line indicates that when translate is called, the implicit argument this will
be equal to p1.
We say that the point p1 performs the translate method.
If the performer of a method is not specified, it is assumed that thisshould perform
the method, so:
translate(0,3,0);

is the same as:


this.translate(0,3,0);

Of course, this only makes sense (is compilable) if this is a Point.

Class Heierarchy
Classes are arranged in a heierarchy (a tree, to be specific).
When you make a new class, you have to say what it is a subclass of (what
its superclass is).
Object is the class at the top.
Every other class is a subclass of Object, or a subclass of a subclass of Object, or so
on.

A subclass automatically inherits all the variables and methods of its superclass. It may also
define new variables and methods. If it wishes, it can override (redefine) some of the inherited
methods.
Here we define a subclass of Point. We say that we are subclassing Point:

class ColoredPoint extends Point {


int colorNumber;
void changeColor() {
colorNumber++;
}
}

Then we could have code like:

ColoredPoint cp;
cp = new ColoredPoint();
cp.x = 4;
cp.y = 5;
cp.z = 6;
cp.colorNumber = 3;
cp.translate(3,0,0);
cp.changeColor();

Kind Of
We see in the above example that a ColoredPoint is a kind of Point.
And in fact, any subclass of Point (or subclass of subclass of Point, etc.) is a kind of
Point.
An Advanced Topic: Interfaces
Sooner or later (probably later), we will inevitably want to say that a class is a kind of
two different things. For example, a Chair might be a kind of Furniture, and it might
also be a kind of ComfortablePlace. How can we do this?
One way this could be is if Furniture is a subclass of ComfortablePlace,
then Chair could be a subclass of Furniture, and it would then be both a kind
of Furniture and a kind of ComfortablePlace.
But this is conceptually wrong, since we would certainly want to allow other kinds
of Furniture which are not a kind of ComfortablePlace, for example a Shelf. We do
not want to force ComfortablePlace and Furniture to have any particular relation to
each other just because Chair happens to be a kind of both.

Some object oriented languages, like C++, allow multiple inheritance, meaning that a class
can have more than one superclass. Other languages, like Objective C and, in particular, Java, do
not allow multiple inheritance, so we will not discuss it any further!
Java's solution to the problem is the Interface. An interface is like a class, except that it has no
variables. It just has a list of methods, and the methods don't even have any code! An interface
doesn't have any instances. So what good is it?
A class can be declared to implement an interface:

class Chair extends Furniture implements ComfortablePlace {


boolean hasArmrests;
boolean canSwivel;
int legs;
boolean occupied;
boolean occupy() { // return whether occupation attempt
succeeds
if (occupied)
return false;
occupied = true;
return true;
}
boolean leave() { // return whether attempt to leave succeeds
occupied = false;
return true;
}
}

Here is what the definition of the ComfortablePlace interface might look like:

interface ComfortablePlace {
boolean occupy(); // return whether attempt succeeds
boolean leave(); // return whether attempt succeeds
}

The compiler, upon seeing that class Chair is declared to implement the
ComfortablePlace interface, will check that this is indeed so.

Now, just as we declared the variable cp above to be of type ColoredPoint, we can declare a
variable to be of type ComfortablePlace. Then the variable is allowed to hold any object that is
of a class implementing ComfortablePlace, and we can invoke any method from
the ComfortablePlace interface:

ComfortablePlace cp;
cp = new Chair();
cp.occupy();

In this way, a Chair is both a kind of Furniture and a kind of ComfortablePlace.

Code
Java code is pretty much nothing but classes. There are no global variables or
precompiler.

Code is written in .java source files (typically one file per class, with the same name as the
class), and compiled into .class class files.

For example, here is a "hello world" program, written as a file HelloWorld.java:


These are like #include statements in C, specifying what libraries (or, more generally, what other classes) will be
used.
They must appear before any class definitions.
import java.applet.Applet;
import java.awt.Graphics;

This says we will define a class called HelloWorld, as a subclass of the already-defined class Applet
public class HelloWorld extends Applet {
Instance variables would go here (or even class variables, indicated with "static"), but we don't happen to have any.
Here we define a method called paint, taking an argument g of type Graphics (that's why we included
java.awt.Graphics above)
public void paint(Graphics g) {
The body of the method is just to call g's drawString method (defined in java.awt.Graphics) with some simple
arguments
g.drawString("Hello world!", 100, 30);
(0,0) is the upper left corner. That starts drawing the string at (100,30).
}
}

To use this applet in a web page, we would use the following html:
<APPLET CODE="HelloWorld.class" WIDTH=200 HEIGHT=30>If this here html is
rendered then your browser can't run applets, perhaps because an option to
enable java is not selected.</APPLET>

This tells the browser that the file "HelloWorld.class" contains a classHelloWorld which must be
a subclass of Applet so that it can respond to all the messages that the browser will send it.
(Applet is in turn a subclass of Panel, then Container, then Component, which can draw and get
events.) We have overridden only the paintmethod.

If you write a Java standalone program (instead of an Applet), then you will use main(), like in
C.
But that's a silly thing to do with Java -- the only real reason to write in Java is to write platform-
independent applets for people to run in their browsers. And for applets, you do not need a
main(). Instead, your Applet subclass (specified in the html) will be sent messages such as
start(), stop(), paint(), etc. These will be discussed at 1:00.

Here is a list of keywords to whet your appetite...

Keywords
abstract type*....................instances not ok, codeless methods ok
boolean type.....................1 bit, true or false (constants)
break flow control......exit switch, loop or labeled block
byte type.....................8 bit signed
case flow control......possibility in a switch
catch flow control......handle a thrown exception
char type.....................16 bit unicode
class type*....................anchor of class declaration
const (unused)
continue flow control......skip remaining code in inner loop
default flow control......catch-all case at end of switch
do flow control......loop: do {code} while (cond);
double type.....................64 bit floating point
else flow control......after if
extends type*....................specify superclass or superinterfaces
final type.....................var: constant, class/method: no subs
finally flow control......code to execute even during exception
float type.....................32 bit floating point
for flow control......loop: for (i=1;i<9;i++) {code}
goto (unused).....................use "break label;" to exit a block
if flow control......branch: if (test) {code} [else {code}]
implements type*....................specify interfaces class adheres to
import compile control...."import java.awt.Graphics;"
instanceof op......."objA instanceof ClassOrInterfaceB"
int type.....................32 bit signed
interface type*....................anchor of interface declaration
long type.....................64 bit signed
native type*....................method body is written in e.g. fortran
new op.......new MyClass(args)inits w/that func
null obj..defined to be unequal to any object
package (type)...scope control...."package mypackage;" marks file
private type.....................visible only within class
protected type.....................visible only to package & subclasses
public type.....................visible to everybody
return flow control......return [a value] from current function
short type.....................16 bit signed
static type.....................specify var or method is "class"
super obj..like "this" but as if in higher class
switch flow control......branch: switch (val) {case 7: code;}
synchronized type.....................only one gnome allowed in at a time
this obj..object the method was called on
throw flow control......abort from code, throwing an exception
throws type*....................specify exceptions method emits
transient(unused).....................not considered part of object's state
try flow control......check for exceptions in a code block
void type.....................the type of 0 bytes of memory
volatile type.....................might be modified asynchronously
while flow control......loop: while (cond) {code}

10:00
This hour we learn the Java language.
Values vs. Variables vs. Types
3 is an integer value. x might be an integer variable, meaning it can hold any integer
value, for example 3. Both 3 and x are of type integer. We often say things like "x is
3", but "is" is misleading -- really, x "holds" 3.

If y is another integer variable, you can't have x hold y. x can only hold an integer value, such as
the value of y. An assignment statement like x=y says that x's value should become what y's
value is.
Some people call variables "lvalues", where the "L" at the front of "lvalue" means that it is
something that can appear on the Left hand side of an assignment. Whether you find this
confusing or clarifying is up to you.
"Automatic" variables are those that are part of some code to execute. This name comes from
how their storage space (on the stack) is automatically created and deleted when the routine is
entered and exited. The only other kind of variable (besides automatic) in Java is an instance (or
class) variable. These terms have to do with scope, not with type.

Types
Java has the following types:
type description
------ -------------------------------------
byte 8 bit signed integer
short 16 bit signed integer
int 32 bit signed integer
long 64 bit signed integer
float 32 bit signed floating point number
double 64 bit signed floating point number
char 16 bit unsigned unicode
boolean one of the two literal values: true or false (not a number)
[name of class or interface]
any object which is a kind of that class or interface
[array type]
any object which is a kind of that
The first eight types listed above (i.e. all but the last two) are called the primitive types,
since they are not defined in terms of anything else -- they are just sequences of bits
that computer cpus are ready to deal with. You are probably already familiar with
types like these, so I won't waste any more words trying to explain them!

Anything that is not a primitive type is a reference type. A reference type is a class, interface, or
array type.
A variable of any reference type may be set to null, meaning that it doesn't hold anything.
(If you are familiar with pointers you will recognize that reference types are pointers to objects.)
The last two types in the table mean that you can use a class or interface name just like you
would use a primitive type. This is pretty neat. Every class is effectively a type. So if myDog is a
variable of type Dog, then any kind of Dog may be assigned to the variable myDog. As another
example, if a variable is of type Object, you can assign any object at all to it.
Dog bigDog = new Dog();
bigDog.fetch(); // This calls the fetch() routine defined in
class Dog
Object anObject = bigDog; // This assignment is ok, since Dog is a kind of
Object
anObject.fetch(); // This is a compile-time error, since fetch()
is
// not defined for Objects
((Dog)anObject).fetch(); // This will work, but if anObject does not
contain a
// kind of Dog when this statement is executed
at
// run-time, then this will generate a
ClassCastException

Even classes themselves are objects, of the class Class, so their type is Class. You don't
normally have to deal with this, but it is reassuring to know that absolutely everything beyond
the primitive types is an object of some class!
There are heaps of "built-in" classes (in the standard libraries), plus of course all the classes you
create.
So there are as many types as you want!
Arrays
The last entry in the table above is for array types. They are represented by having
any of the previous types followed by some number of []'s, one for each dimension of
the array. So Dog[] is an array of Dog's, and int[][][]is a 3D array of ints. Array
types are classes like any other class, and arrays are objects like any other object. For
example, an array has an instance variable length that says how big the array is. So
if mat is a variable of type int[][], then mat.length tells how many int[] rows it has,
and mat[3].lengthgives the length of the third row. The size of a dimension is not a
part of the type. Such sizes are aspects of the values that get assigned.
int[][] mat; // mat === null (mat, as an object, defaults to
null)
mat = new int[2][2]; // mat === {{0,0}, {0,0}}
mat = new int[3][]; // mat === {null, null, null}
mat[0] = new int[4]; // mat === {{0,0,0,0}, null, null}
mat[1] = new int[3]; // mat === {{0,0,0,0}, {0,0,0}, null}
mat[2] = new int[2]; // mat === {{0,0,0,0}, {0,0,0}, {0,0}}
mat[0][2] = 7; // mat === {{0,0,7,0}, {0,0,0}, {0,0}}
mat[3][2] = 4; // throws IndexOutOfBoundsException

If you have an array of type Dog[], then each member of the array can be any kind of Dog.
Dog[] dogList = new Dog[5]; // dogList holds {null, null, null, null,
null}
new Dog[5] creates space to hold 5 dogs -- it creates 5 variables of type Dog. These variables are
each initialized to null until you assign something else to them.

The source code can contain an explicitly typed-out array, but for some reason only in an
initializer:
int[][] mat = {{2,3},{4,5}}; // this is ok
mat = {{6,7},{8,9}}; // but this won't compile!

For some reason, the run-time names of array classes are different from how you specify them in
the source code -- an array of ints is int[] in the source code but "[I" at run time. I can't
imagine why this is.
A Very Subtle Point:
If you have a variable dogList of type Dog[], then you can also assign dogListto be an array of
type SeeingEyeDog[]assuming SeeingEyeDog is a kind of Dog. But then you need to be careful
that you won't be hit by the following potential run-time problem: If you say dogList[3] =
stupidDog (which looks fine to the compiler as long as stupidDog is a kind of Dog),
an ArrayStoreException can be thrown, since an array of type SeeingEyeDog[]cannot
contain stupidDog if stupidDog is not a kind of SeeingEyeDog.

Initialization
Objects are always initialized to nullunless they are explicitly initialized otherwise.
Primitive-type variables fall into two categories: Automatic ones must be initialized
before use. Instance (or class) ones are automatically initialized to 0 or false.

If an automatic variable is not initialized before it is used, that is a compile-time error. Here's
how the compiler decides whether something is initialized:

Change all values (except for boolean constant expressions) to "blah".


Then, see if you can still tell that the variable must necessarily have been
assigned, considering just the possible flows of control (including
boolean-switched evaluation like &&, ||, ?...:). Also,
consider try statements to be capable of immediately throwing any
exception.
int b; | | int b;
while (3>5) { | | while (false) {
b = 3; | | b = blah;
} | | }
foo(b); | | blah(b); // b not
initialized
| |
int c; | | int c;
if (flag) | | if (blah)
c = 14; | | c = blah;
else | | else
c = 17; | | c = blah;
foo(c); | | blah(c); // c is
initialized
| |
int d; | | int d;
if (flag) | | if (blah)
d = 20; | | d = blah;
if (!flag) | | if (blah)
d = 30; | becomes | d = blah;
foo(d); | | blah(d); // d not
initialized!
| |
int e; | | int e;
if (flag || !flag) | | if (blah || blah)
e = 5; | | e = blah;
if (flag && !flag) | | if (blah && blah)
foo(e); | | blah(e); // e not
initialized!
| |
boolean f; | | boolean f;
if (flag && (f=true)) | | if (blah && (f=true))
foo(f); | | blah(f); // f is
initialized
| |
boolean g; | | boolean g;
if (flag || (g=true)) | | if (blah || (g=true))
foo(g); | | blah(g); // g not
initialized
| |
int t; | | int t;
try { | | try {
t = 5; | | t = blah;
foo(t); | | blah(t); // t is
initialized
throw(new MyException()); | | throw(blah);
} catch (MyException e) { | | } catch (blah) {
foo(t); | | blah(t); // t not
initialized!
} | | }

Classes
For convenience, there are classes corresponding to each of the primitive types.
For example, the Integer class has a constructor to make an integer from a string, and
an intValue() method that returns an int:
if (getParameter("side") != null)
side = (new Integer(getParameter("side"))).intValue();
Strings
Strings are totally objects, members of the class String. They are not arrays of
characters like in C. If the source code contains "hello", it will be compiled as a String
object.
int theLen = "A String".length();
The + operator concatenates strings, promoting first if necessary.
x = "a" + 4 + "c"
is compiled to the equivalent of:
x = new StringBuffer().append("a").append(4).append("c").toString()
I don't know whether "value = "+3+4 is supposed to result in "value = 34" or "value =
7".
(Note that in Java, the "just try it and see" method can lead to big trouble: Perhaps the
Java specification does not specify the answer, in which case you will of course find
some answer when you try it and see on your computer, but then when you write code
based on what you learned, your code won't work on other people's computers, which
have different Java implementations.)
You can't mess with the contents of a String. If you want to, use a StringBuffer
instead.

Variable Scope
A variable's scope is from its declaration to the end of the block it is declared in.
The declaration need not be at the beginning of a block:
for (int i = 1; i < 10; i++)
But you can't declare after a comma, so you can't do:
for (int i = 1, byte j = 10; i < 10; i++, j--) // WON'T COMPILE!
What's really going on in that example? The first "int" means that everything up to
the next ; is a declaration. But the next ; also delineates the next part of the for. So
the whole first part must be an int declaration.
But even the following is no good:
int i;
for (i = 1, byte j = 10; i < 10; i++, j--) // WON'T COMPILE!
If it's so hard to declare in for loops, I don't see why it's allowed at all.
Here's the answer: Java has a hack that lets the initialization of a for loop (but no
other weird place) be an initializer. This means that it starts with a type, and then as
many variables as you want of that one type, each initialized if you wish. So
you cando:
for (int i = 1, j = 10; i < 10; i++, j--) // compiles ok

Note that if you declare a variable inside a loop, then it is undefined for the part of the loop prior
to its declaration, and its initialization, if any, will be performed for every pass of the loop.

Operations
Java basically has all the same operators as C, but + can concatenate strings,
and >>> shifts right filling with zero (not the sign bit).
Floating point values as well as integer values can be incremented and decremented
with ++ and --.
For boolean values, & and && are the same except that && won't evaluate its second
argument if the first argument was false. Or'ing is similar.
Floating point operations never produce exceptions (they can produce NaN though), and
integer operations only generate an ArithmeticException upon /0 or %0.
A boolean can't be cast to or from anything else.
Casts between different integer types either drop bits (to shrink) or extend the sign bit
(to grow).
Casts involving floating point numbers always result in the representable value closest
to the original value, except: If the final type is less than 32 bits, first it converts to a
32-bit integer, and then it chops off bits. In particular, very large (or infinite) positive
values become -1 and large negative values become 0!
If NaN is cast to an integer, it becomes 0.

[[prioritized list of ops]]

Control Flow
Very simple. Same as C. Hope you know C!
There are only a couple of differences: exceptions, labeled break/continue, and no
goto.

Labeled Break and Continue


A block or statement can have a label, say foo:{some code}. Then, if, inside the labeled part,
a break foo; is encountered, the labeled section will immediately be exited. If a continue
foo; is encountered, the labeled part (which must be a for, do, or whilestatement) will
immediately be continued.

Method Declaration
[accessSpecifier] [static] [abstract] [final]
[native] [synchronized] returnType methodName ([paramlist])
[throws exceptionsList]

static means the method is a class method -- it may be invoked by ClassName.methodName as


well as instance.methodName (there is no difference -- use whichever is handier).
A static method therefore cannot use instance variables, or this, since there may not even be any
instance in existence!
abstract means the method has no code -- a subclass must override (redefine) the method,
supplying code. In this case, the declaration is followed by a semicolon instead of code.
final is the opposite of abstract -- it means that subclasses are not allowed to override the
method.
native means the the code for the method is written in some language other than java. We will
not discuss this sort of weirdness.
The return type may be a type, or void. If the return type is void, then no value is returned. No
return statement is needed, and if there is one (for example to return from a point other than the
end of the function's code), it must omit the value. (It may not even specify a "void" value,
e.g. return voidFunction(3,5); is not allowed.)

Variable Declaration
Instance variables are declared in a class definition like this:
[accessSpecifier] [static] [final]
[transient] [volatile] type varName [= init];

static means the variable is a class variable -- there is only one copy of this variable, no matter
how many instances exist. Instances do not have their own copy of this variable -- they all share
the one unique copy.
The variable may be referenced as ClassName.varName as well as instance.varName (there is
no difference -- use whichever is handier).
final means that the value of the variable, specified by the init at the end of the declaration,
will never change. This means the compiler can treat it as a constant, rather than creating storage
for it, and perhaps make other optimizations as well.
transient means that the variable should not be considered part of the object when the object is
being archived. What does this mean? Who knows. Current versions of Java all ignore this
anyway!
volatile means that the variable can be changed asynchronously, and the compiler should
specifically avoid optimizations that assume the variable's value to be, say, the same as what it
was the last time you looked.
The init is executed when a new instance is created (or when the class is created, if static),
prior to the execution of the constructor.

Access Specifiers
Access specifiers are to help make code modular and reusable, by clearly specifying
the scope of a class, class variable, or method.
Small programs can ignore them for the most part, but packages should use them
carefully.

There are four scope levels that can be specified:


private | package | protected | public

A class's code can always access member variables of objects of that class -- but if the
variable is private, then nothing else can see it, even within the package.
A package variable (the default -- there's no need to explicitly specify this) is visible
only within the package.
A protected variable is also visible to subclasses outside the package, but only for
objects of those subclasses. (why???)
And finally, a public variable is accessible by code anywhere.

Are these compile-time or run-time restrictions? Run-time!


That is, at run time you can ask what methods a class implements, and so on.
"Static" variables or methods are class variables and methods.

What does a public method mean for a non-public class?


For example, interface methods must be public. But why, if the interface isn't public?
An abstract method may only appear in an abstract class.
You can't have an abstract static method. Why?
All methods in a final class are automatically final. The same is true for private methods.
If a method is static and has no type or name, then it is init code for the class.
Why can't a constructor be synchronized (or anything else)?

Interfaces
An interface is like a protocol in Objective C. But anyway...
An interface is a list of methods and constants.
A class "implements" the interface if it implements all of the methods in the list.

You declare an interface like this:


[public] interface Pokable [extends Botherable, Malleable] {
int JAB = 8, TICKLE = 3;
void pokeMe(PokerObject poker);
boolean beenPoked(void);
}

If "public" is present, then the interface will be available outside the package.
Extended interfaces can have methods or constants hidden by the new interface.
All the methods are automatically "public abstract".
All the constants are automatically "public static final".
class Pig extends LiveStock implements Pokable, Feedable {
void PokeMe(PokerObject poker) {
}
void FeedMe(FoodObject feed) {
}
boolean beenPoked(void) {
return true;
}
}

Interfaces may be used as variable types!

Class Declaration
[public] [abstract | final] class ClassName [extends SuperClassName]
[implements InterfaceName1 [,InterfaceName2]...]
{
in any order:
instance vars (class vars marked by "static")
(these can shadow inherited vars! "super." may help, or may
not...)
instance methods (class methods marked by "static")
(same goes here)
static {init code that gets executed when class is loaded}
}
If you don't specify a superclass, "Object" is assumed.
Public classes must appear in a file with the same name as the class. Why?

Constructors
super(arg1,arg2); executes the superclass's (relative to the class of the method in
which it appears) appropriate constructor method.

new Point(3) creates and returns a new instance of the Point class.
It's code sets this.x, this.y, or whatever it needs to. It behaves syntactically as if it is type void.
The method Point(int n) is a "constructor" because it has the same name as its class -- it gets
called automatically (by "new") after the instance has been created, to give the instance a chance
to do some automatic initialization of its state. There can be different constructors (distinguished
by taking different numbers or types of arguments).
How can one constructor call another (to avoid duplicating initialization code)?
The first line of a constructor may be this(args); or super(args);, indicating that another
constructor should be executed before the remainder of the body of this constructor is executed.
If there is no such first line, then super(); is assumed.
If no constructor is supplied, then one with no arguments, calling super(), is assumed.
The method finalize() is a "destructor" because its name is "finalize" -- it gets called
automatically by the garbage collector just before the instance is destroyed, to give the instance a
chance to do some automatic "finalization" (the opposite of "initialization"), such as closing
streams. It should probably end with
super.finalize();

Packages
Libraries (collections of functions) are called "packages" in Java.

After you understand the syntax and semantics of the Java language, the main thing you will
spend time learning about is the large set of classes that are a standard part of Java. You will
learn about classes that enable you to get input, produce output, and do countless other things.
These classes are supplied as packages.
You can make a package like this:
package graphics; // applies to this whole file

interface Draggable {
. . .
}

class Circle {
. . .
}

class Rectangle {
. . .
}

All files containing the package graphics line will be considered to be in


your graphics package.
That line must be the first one in the file???
The resulting .class files must be placed in a "graphics" directory on the CLASSPATH.
The package name can have internal period-separators.
If you don't specify a package, you are in the "default package", which is always imported.
Remember that only public methods and interfaces are visible outside the package.
You can import by:
import graphics.Circle;
or
import graphics.*;

What does import really mean???

If the same class is in two packages you have imported, you can specify which class you intend
by prepending the package name to the class name:
graphics.Circle

11:00
You want to do several things at once?
Or stop suddenly but gracefully?
This hour we'll learn about two different things:
Threads, and Exceptions
The concepts needed for thinking about these are introduced,
since you can't avoid dealing with these in Java,
and Java's mechanisms for dealing with them are shown.
Gnomes
Normally, in your program, there is a flow of control. You can tell the flow how to go
by calling functions, using loops, etc. It is like there is one little bustling gnome, being
told what to do as it goes from line to line of your code.

A natural idea, especially when you want your program to do two unrelated activities, is to let
there be more than one gnome. Each gnome can then follow code around, line by line. Of course,
you will need to take care that they aren't each messing with variables that the other is using --
that would cause a lot of confusion for the poor gnomes, and their algorithms would be ruined!
All the object-oriented metaphors talk about the "object" performing the activities described in
its methods. Don't be fooled! Gnomes do the work. For example, one object can do two things at
once, if two gnomes are executing its code. If an object doesn't have any gnomes doing work for
it (and this is usually the case for most objects, since there are typically many more objects than
gnomes), then it can't do anything at all until a gnome arrives on the scene. And in fact, the
gnome manipulates the object, not the other way around. The only "control" the object has over
anything is that in some sense the code represents the will of the object. A method is something
that the object might be asked to do. The code for the method represents how that kind of object
chooses to respond to that request, and it is executed by any gnome that is sent to that method.
Objects never get to do anything except respond to requests and messages. (Often the requests
are actually sent from the object to itself. For example, an object that is asked to go to the next
room might first ask itself to stand up, and then ask itself to walk in a certain direction.) "Being
asked to do something" means that a gnome is sent to the object's method for responding to that
request. When the gnome is done handling a request, it returns to the higher-level request that it
had previously been working on. The object-oriented jargon talks about a "method" being
"invoked" or a "message" being sent. Really, a gnome is sent. Sometimes the gnome is sent with
a message, and sometimes it is sent with a request. The only difference is in your mind. A gnome
always arrives just to perform a specific method, and when it is done, it leaves. They have an
incredibly strong work ethic.

Threads
Computer gnomes wear rather threadbare clothes compared to their cousins in the
forest, and so the unfortunate slang term "thread" arose for these gnomes. However,
their hard work has earned this term a lot of respect, and now they even call
themselves "threads" with pride!

In Java, each gnome (each thread) has a Thread object associated with it. This object stores the
name of the thread, along with any other knick-knacks a thread might desire. The thread itself is
just running around mindlessly executing code, and has no memory or sense of self. Actually,
that's not quite true. It has its own call stack, where it keeps passed arguments, local variables,
and return values. And it knows where its Thread object is. That is where it stores its name and
so on. This can come in handy for example if you have different instructions for different threads
(you would have instructions like "if your name is Sam, do such and such").
Thread.currentThread() is an introspective class method -- if you send a gnome off to execute
this method, then it will come back with its associated Thread object.
new Thread(name) creates a new soulless instance of the Thread class, a "missing gnome" file.
If a gnome X executes the start() method for a "missing gnome" object, then the "missing
gnome" comes into being as a real live gnome Y, and Y runs off to execute its run() method. The
original gnome X just returns to its caller, without worrying about what the new gnome is up to.
If the new gnome Y ever returns from the run() method, it is automatically and painlessly
terminated.
When Y comes into being, it looks for its run() method. It may have one itself, if it is a subclass
of Thread that has a run() method. But it might not have one -- then it looks for a run() method
of its "target" object. What is its target?
new Thread(obj,name) makes a new instance of the Thread class, which has obj as its "target".
The class of obj should implement Runnable (have a run() method).
There are various methods of the Thread object that control the activity of the associated gnome:
(I think they all also exist as class methods, operating on the gnome that executes them.)
The stop() method immediately and painlessly terminates the gnome (by
throwing a ThreadDeath error exception at it!). If the gnome had not yet been
created (i.e. it was a "missing gnome"), it doesn't matter -- it is quite dead after
this, and has no chance at life. This is an asynchronous death, so for gnomes
that could leave things in a disordered state, it is better to set some flag that
they can check at a safe time, killing themselves if they find it set.
The sleep() method causes the gnome to immediately fall asleep for the
specified number of milliseconds. When it wakes up, it will continue where it
left off.
The suspend() method puts it to sleep until someone else executes its resume()
method.
If the thread calls wait(), then it sleeps until that thing calls notify() or
notifyAll().
If a gnome is supposed to do some I/O on a device that is busy, it will fall
asleep until the device is free. This is probably implemented with the above
strategies.
You can setPriority(p) with Thread.MIN_PRIORITY <= p <=
Thread.MAX_PRIORITY
or setDaemon(true) (interpreter will exit when only daemon threads remain).

Synchronization
Sometimes there might be different gnomes that need to work with the same data.
They can't both work on the data at the same time, or terrible things could happen:
Gnome 1 Gnome 2
------------------------- -------------------------
pick up the scissors
pick up the scissors
put fabric 2 in scissors
position fabric correctly
put fabric 1 in scissors
cut fabric
position fabric correctly
put fabric down
cut fabric
put fabric down
Here each gnome is doing something that by itself seems sensible. But at the same
time, another gnome is messing around with the same scissors, and the result is
disaster! Gnome 2 is cutting the wrong fabric in the wrong place, and Gnome 1 winds
up snipping thin air! This just goes to show how brainless threads are. They are so
busy working that they never look up to see if what they're doing makes any sense.

People usually solve this in the following way: Whoever gets to the scissors first gets to use them
until they are done, at which point they give the scissors to the other person, who had to idly wait
until they got the scissors.
From an object-oriented point of view, we might have an object theScissors, with a method
cutFabric(). To solve the problem of thread brainlessness, theScissors would know that there are
certain activities that are only safe for one gnome to do at a time, such as cutting fabric. Such
activities (methods) are marked with the keyword "synchronized". Any time any thread wants to
start executing synchronized code, it will first make sure no one else is doing so for that object. If
someone else is doing so, it has to wait its turn. But once it is executing the synchronized code, it
can be sure nobody else will do so until it has finished.
The way this works is that there is a solid gold baby monitor excavated from the tomb of
Cheops. This item is popular with objects, but since the real article is in the London museum,
each object just has a little gold-tone plastic replica. There is a bizarre tradition dictating that
gnomes may only enter "synchronized" code if they have the object's baby monitor. Only one
gnome can have the monitor at a time, so if a gnome enters synchronized code on behalf of a
certain object, no other gnomes may do so until it has finished with the synchronized code, thus
relinquishing the monitor.
synchronized (myObject) {code executed when myObject's monitor is obtained}
wait() -- sleep until notified (letting go of monitor)

notify(), notifyAll() -- wake up all waiters.


These can only be called when you have the monitor -- why???
Are constructors automatically synchronized? The docs say it can't matter, since nothing else
can see the object before the constructor finishes. That doesn't seem right, though. ???

Exceptions
try {code that might throw exceptions}
catch (MyThrowable var1) {...}
catch (Throwable var) {...}
finally {...}
If an Error or Exception is thrown, then the first (if any) applicable catch is executed.
In any event, the finally block is executed, even if the remainder of the function will
be skipped due to an active exception..

Here's how to indicate that your routine may emit a throwable instead of its return value:
public void writeList throws IOException, ArrayIndexOutOfBoundsException
{...}
Here's how things are thrown:
throw aThrowable;
Runtime exceptions can happen from any function -- functions do not need to declare
that they might throw them.
Examples are 1/0, null.x, a[-3], etc.

There are two built-in kinds of Throwable:


 Error, for bad conditions that one is not expected to recover from

(an error in the runtime system, or in a dynamically loaded class file, or a


ThreadDeath)
 Exception, for trip-ups that a program should be able to recover from

(mostly IO -- things the code might hope won't happen, but can't tell in
advance)
o RuntimeException, for when a program goofs up

(in arithmetic, using arrays, etc. -- things a careful code-examiner could


have predicted)
Exceptions that are not RuntimeExceptions, therefore, are trip-ups that a program
should be ready for, such as file-not-found when trying to open a file, etc.

Let's consider the FileNotFoundException. You might think that a careful program could first
check to make sure the file exists, and only open it if it exists. But even this is not 100% safe --
another program could delete the file after you checked that it exists, but before you opened it.
The only way to really tell whether you can open it is to just try, and see whether you succeed or
fail. In Java, failure is indicated by an exception being thrown.
As such, the compiler requires that such exceptions be specified in the function declaration if
they might be thrown by the function. So if you have a function that opens a file, and it doesn't
bother to catch the file-not-found exception, then the exception will be thrown to the calling
function -- the function declaration must specify this, so that callers know to expect the
exception.

12:00
Lunch Break
You are done learning the language.
Hungry? Go eat lunch.

1:00
You want interactive buttons and pictures?
This hour we will learn about GUI stuff.

The Java Run-Time Environment


Java's environment is essentially Yet Another Windowing Narcissism.

Instead of a simpler GUI model, we are faced with yet another windowing system whose
complexity is comparable to previous windowing systems. That is, it is a huge bureaucracy of
events, drawing commands, and so on.
AWT == Abstract Windowing Toolkit
We will try to separate the bureaucracies from each other to simplify the picture.

 Coming into (and out of) existence as an application or applet


o Housing bureaucracy
o Thread bureaucracy
o Parameter bureaucracy
 Receiving gui input and notifications
o Event bureaucracy
o Button, slider, etc. bureaucracy
 Producing gui output
o Container and layout bureaucracy
o Drawing bureaucracy
o Image bureaucracy
o Sound bureaucracy
 Communicating with other programs or the host machine
o Browser bureaucracy
o Inter-applet bureaucracy
o Security bureaucracy
o System bureaucracy

Housing Bureaucracy
The browser sends the applet various messages in relation to giving it a home or a job.
import java.applet.Applet;

 public void init() - called when applet is loaded -- better to do initialization here
than in the constructor, since much of the support (for example the ability to
load images) has not yet been constructed at applet construction time.
 public void start() - called when page gets shown
 public void stop() - called when page disappears
 public void destroy() - called when applet is unloaded (when would this
happen???)
Thread Bureaucracy

 notifyAll -- a synchronized method -- wakes up threads waiting for the monitor


 notify -- a version that wakes up only one thread at random (when is this
good???)
 wait -- in synchronized code -- go to sleep until woken up, relinquishing
monitor in the meantime
 wait(long timeout) -- only nap for timout milliseconds
Parameter Bureaucracy
Parameters inside the <applet ...> tag are for the browser to be able to run the applet.
Parameters between <applet ...> and </applet> are like command-line arguments to
the applet.
<Applet
Code="MyApplet.class"
Width=200
Height=100
CodeBase="http://myco.com/~mysource/"
Alt="Your browser understands APPLET but can't run applets."
Name="instance 5"
Align=top
VSpace=10
HSpace=20
>
<Param Name=InnerMethod Value="3">
<Param Name=OuterMethod Value="bubbling">
Html to appear in browsers that don't understand the APPLET tag.
</Applet>
The first three (code, width, height) are required. The rest are not. The order doesn't matter.
The last three are the same as for the IMG tag. The html keywords are all case-insensitive.
"Codebase" lets you specify an absolute url. (The default is the url of the html page.) The
"code" file must be relative to this, not absolute.
In the "param" tag, the "value" field is always passed to the applet as a string, regardless of
whether quotes are used.
The java code can read a parameter like this:
String outerMethod = myApplet.getParameter("OuterMethod");
This will return null if there is no such parameter supplied!
This must be done in the applet's init() or later -- doing it in the constructor fails badly.
You can get values of parameters inside the APPLET tag in just the same way.
Methods such as Integer.parseInt (throws NumberFormatException) can be useful for turning the
string into a preferred type.
Extremely interactive environments will be able to show a page writer the following information
if you supply this method in your applet subclass:
public String[][] getParameterInfo() {
String[][] info = {
// Parameter Name Kind of Value Description
{"InnerMethod", "int", "number of approximations to
make"},
{"OuterMethod", "activity", "bubbling, snorting, or
whizzing"}};
return info;
}

Event Bureaucracy
Events have changed with Java 1.1. But my Netscape 4 can only handle the old style,
so that's what I discuss.

Events are passed up the container heierarchy by default.


You can look at, alter, or stop an event before it continues up the heierarchy.
An event arrives at a component in the handleEvent() method, which dispatches the event to the
appropriate handler according to its type. If you override this, you probably want to return
super.handleEvent to take care of the dispatching (e.g. otherwise action events can't get
generated).
import java.awt.Event;

 action() // sent by buttons, etc.


 mouseEnter(), mouseExit(), mouseMove(), mouseDown(), mouseDrag(),
mouseUp()
 keyDown(), keyUp()
 gotFocus(), lostFocus
These are public boolean functions that return true if the event should stop going up
the container heierarchy.

An Event e has a type, target, timestamp, location, keyPressed, data, modifierKeys.


e.type
Button, slider, etc. bureaucracy
These classes are java.awt.gizmoname, where gizmoname is one of:
Button, Checkbox, TextField, TextArea, Label, List, Choice, Scrollbar, Canvas, Menu,
MenuItem, CheckboxMenuItem, Panel, Window, etc.
An object containing such a control will have its action() method called if the control
receives an event.

Container and Layout Bureaucracy

 add
 remove
 setLayout
 validate -- creates peers for all the contents (done automatically if about to be
shown for first time), causing them to be drawn
 GridBagLayout
 BorderLayout
Outer components are drawn, then inner ones (ones they contain) (in no particular
order).
Every component must be in a container if it wants to be shown.
A Container is a kind of Component.
The only exception is the top-level container -- a Window.
There are two kinds of Windows: A Frame is a first-class window, while a Dialog is a
subsidiary window.
A Panel groups things together in part of a display area.
A Container uses a LayoutManager to control the layout of its stuff.

What is a LayoutManager?
Every
There are several pre-supplied layout managers, or you can write your own.
Drawing bureaucracy
import java.awt.Graphics;

 public void paint(Graphics g) - draw yourself - default does nothing - executed


by the AWT's inimitable drawing gnome
 update(Graphics g) -- executed by the drawing gnome - default draws a gray
rectangle and calls paint() - this sequence can lead to "flashing"
 repaint() -- puts update() in the drawing gnome's queue of things to get around
to - can specify a subrect to be painted
The drawing gnome sometimes calls paint() directly, e.g. if the window gets
uncovered.
You could put the drawing commands in update() and have paint() call update() if you
wanted.
But why is there both an update() method and a paint() method?

"Double buffering" is just drawing into an image, and then painting by copying the image. See
Image Bureaucracy.
A Graphics object represents a drawing context, and lets you draw empty/filled rectangles, arcs,
lines, ovals, polygons, text, and images. The following examples operate on graphics object g.
Coordinates are in pixels, with y increasing as it goes down.

 g.drawLine(ax, ay, bx, by);


If you want to draw just a single pixel, you have to do something silly like
drawLine(x,y,x,y).
The following drawing commands all also have a "fill" version, starting with "fill"
instead of "draw".

 g.drawRect(minX, minY, width, height);


 g.draw3DRect(minX, minY, width, height, isRaised);
 g.drawRoundRect(minX, minY, width, height, arcWidth, arcHeight);
 g.drawOval(minX, minY, width, height);
 g.drawArc(minX, minY, width, height, startAngle, endAngle);
 g.drawPolygon(polygon);
To make a polygon, use "new Polygon", and then addPoint(x,y) to it repeatedly.
drawPolygon doesn't close the polygon, but fillPolygon does, and uses even/odd fill.
 g.drawString("Hello World!", minX, baselineY);
 g.drawImage(
The drawing color is initially the Component's foreground color. "Clearing" color is
Component's background color.
The Graphics object also lets you get/set color, font, clipping area, paint mode

Image bureaucracy

 getImage
Here's an example of how to do "double buffering":
Dimension dbDims; Image dbImage; Graphics dbGraphics;
if (dbGraphics == null || d.width != offDimension.width
|| d.height != offDimension.height) {
dbDimension = d;
dbImage = createImage(d.width, d.height);
dbGraphics = dbImage.getGraphics();
}
// draw into our image
dbGraphics.setColor(getBackground());
dbGraphics.fillRect(0, 0, d.width, d.height);
dbGraphics.setColor(Color.black);
dbGraphics.fillRect(x, y, w, h);
// copy the image to the screen
g.drawImage(dbImage, 0, 0, this);

Even the init is in the update() method because until then we don't know what size we are.

Sound bureaucracy

 getAudioClip(URL [,string] ) -- returns an object that implements AudioClip


 play -- same as above but plays it
 AudioClip interface: loop, play (once), stop (immediately)
Browser bureaucracy

 showStatus("MyApplet: Loading image file " + file);


 standard output and error sent to java console in netscape.
 System.out.println("Called someMethod(" + x + "," + y + ")"); // can use err as
well as out
 tell browser to show URL: public void showDocument(java.net.URL url [,
String targetWindow] )
 targetWindow can be: "_blank" (new window), [windowName] (maybe new),
"_self" (applet's window & frame), "_parent" (one frame up from applet),
"_top" (highest frame in applet's window)
Inter-applet bureaucracy

 you can invoke public methods of other applets on the same page
 the java.net package lets you communicate with programs running on the
machine
 String host = getCodeBase().getHost(); // tells what host the applet came from
 you can use sockets and a demon on the applet source's machine to enable
communication between multiple viewers
Security bureaucracy
System Bureaucracy

 String s = System.getProperty("os.name");
 file.separator, java.class.version, java.vendor, java.vendor.url, java.version,
line.separator, os.arch, os.name, path.separator

doc bugs:
sun:
of course sound creation returns immediately -- it is specified to do so -- sound only
loaded when played
lang spec:
atan2 has arguments in other order

stupidities:
flow control not improved -- it's still a pain to decide whether every linked list in a square array
contains a predator
interface methods must be public, so the compliant methods must be public,
so a public class is forced to expose interface-related methods regardless of whether they should
be visible outside the package

Das könnte Ihnen auch gefallen