This is a beginners' review of Java intended for people that are already programmers, our table of contents and basic reference material for the QuizSite Java exercises to be posted later this week.
1. Abstraction, Encapsulation, Inheritance, and Polymorphism
Abstraction is the process of refining away the unimportant details of an object, so that only the appropriate characteristics that describe it remain. These, together with the operations on the data, form an abstract data type (ADT). Abstraction is where program design starts. All mainstream programming languages provide a way to store pieces of related data together. It is usually called something like a structure or a record.
Encapsulation means grouping together the types, data, and functions that make up a class, and providing some information hiding to control access. In C, for example, a header file provides a very weak example of encapsulation, because it is a purely lexical convention, and the compiler knows nothing about the header file as a semantic unit.
Non-object-oriented programming languages support encapsulation very well for built-in types, and not at all for user-defined types. Take, for example, floating point numbers: in most languages the only valid thing you can do with them is arithmetic operations and I/O. Even in C, if you try to shift left the bits of a floating point number the compiler will print out an error message. The valid operations for a float are encapsulated (bundled together) as part of the type information, and shifting isn't one of them. The compiler enforces the rule that "the operation must be compatible with the type".
Object-oriented programming languages extend the support for encapsulation (bundling together types and the functions that operate on those types, and restricting access to the internal representation) to also cover user-defined types. They enforce the integrity of a type by preventing programmers access individual fields in inappropriate ways. Only a predetermined group of functions can access the data fields.
The collective term for "datatype and operations bundled together, with access restrictions" is a class. The individual elements in a class are fields. A variable of some class type is called and instance (or an object). It's pretty much the same as a variable of an ordinary type except the valid functions that can be invoked for it are tied to it.
Some class terminology
Constructors and Finalizers A constructor is a special kind of method that initializes a newly-created object. There are no destructors in Java (in the C++ sense) because the memory management is automatic. You can provide a finalizer for a class, and it will be invoked on an object right before it is garbage collected.
Inheritance means being able to declare a type which builds on the fields (data and methods) of a previously-declared type. As well as inheriting all the operations and data you get a chance to declare your own versions and new versions of the methods, to refine, specialize, replace or extend the ones in the parent class.
Casting Casting is the C term for type conversion, carried over into Java.
Inheritance and Constructors
this
reference.
Abstract and Final
abstract and final are somewhat opposites of
each other:
Multiple inheritance per se does not exist in Java, but it can be simulated with interfaces (as we shall review later).
Visibility and Other Name Modifiers
Class ModifiersThe fields in a class body can be variables, or methods.modifier class name [extends name] [implements namelist] bodyThe modifier can be one or more of:
abstract- class must be extended to be usefulfinal- class cannot be extendedpublic- class is visible in other packagesabstractandfinalare opposites and are not allowed together.
The field can similarly start with a modifier that says how visible it is, and qualifies it in some other way.
| Data Field Modifiers | |
| Visibility | |
public | field is visible everywhere (class must be public too) |
| <blank> | what you get by default. Field is only visible in this package. |
protected | like default, and the field is visible in subclasses in other packages extended from this class, too |
private | field is only visible in this class |
| Behaviour | |
static | one per class, not one for each object |
final | cannot change value |
transient | a hint used in object serialization |
volatile | this data may be written to by several threads of control, so the run time system has to take care to always get the freshest value when reading it |
| Method Field Modifiers | |
| Visibility | |
public | field is visible everywhere (the class must be public too) |
| <blank> | the default (field is visible in this package) |
protected | like default, and the field is visible in subclasses in other packages extended from this class |
private | field is only visible in this class |
| Behaviour | |
final | cannot be overridden |
static | one per class, not one for each object |
abstract | must be overridden (to be useful) |
native | not written in Java (no body, but otherwise normal, and can be inherited, static, etc.) The body will be written in another language. |
synchronized | only one thread may execute in this method at a time. Entry to the method is protected by a monitor lock around it. |
Static There are three varieties of a static thing
(once only) in Java. A static thing is something
in a class that occurs once only, instead of once for each instance of
the class.
Polymorphism means reusing the same name for a related concept on different types. The trivial kind of polymorphism is called overloading and it means that in any class you can use the same name for several different (but hopefully related) methods. The second, more complicated kind of polymorphism (true polymorhism), is resolved dynamically (at run time). It occurs when a subclass has a method with the same name and signature (that is, number, type and order of parameters) as a method in the superclass. When this happens, the method in the derived class overrides the method in the superclass.
Example
class Fruit {
int grams;
int cals_per_gram;
int total_calories() { /* ... */ }
void peel() { System.out.println("Peel a Fruit"); }
}
class Citrus extends Fruit {
void squeeze() { /* ... */ }
void peel() { System.out.println("Peel a Citrus"); }
}
class Example {
public static void main (String args[]) {
Fruit somefruit = new Fruit();
Citrus lemon = new Citrus();
somefruit.peel(); // [1] Fruit
lemon.peel();
somefruit = lemon;
somefruit.peel(); // [2] Citrus
}
}
Terminology
- class
- a (user-defined) data type
- extend
- to make a new class that inherits the contents of an existing class, the class that it extends
- superclass
- a parent (or "base") class
- subclass
- a child class that inherits, or extends, a superclass
| Concept | Java term | C++ term |
|---|---|---|
| function in class | method | member function (member method) |
| class that is expected to be extended | abstract | virtual |
| anything in class | field | member |
| parent relationship with another class | extend | inherit |
| class you extend | superclass | base class |
| extended class | subclass | derived class |
| initialization | method constructor | constructor |
| finalization method | finalizer (in part) | destructor |
2. The Language The Anatomy of an Application
class pentium {
public static void main(String args[]) {
double x, y, z;
x = 4195835.0; y = 3145727.0;
z = x - (x / y) * y;
System.out.println("results = " + z);
}
}
As in C the signature of main() is magic and it tells the runtime system
to start execution here (with it). In Java main() is defined to return a
void (no value). In C it is defined to return an int.
The modifiers say that this function is visible everywhere (public)
and it is a method for the class as a whole, not specific to individual objects
(static).
The rest of the code is self-explanatory.
Identifiers, Comments, Keywords, Operators
Identifiers can be any length, and they must start with a letter, underscore, or dollar sign, and in subsequent positions can also contain digits. Java has been designed with internationalization in mind, and it uses the 16-bit Unicode character set.
Commenting out code can be done in several ways:
// to the end of line
/* anything in between */
if (false) {
what needs to be skipped
}
boolean true false char byte short int long float double void
null new this super
if else switch case break default
for continue do while
return throw
synchronized try catch finally
static abstract final private protected public transient volatile
class instanceof throws native
extends interface implements package import
cast const future generic goto inner operator outer rest var
Operators
A C or C++ programmer will be readily familiar with the operators in Java. The novel aspect is that the order of evaluation is well-defined.
The Java order of evaluation says that for all binary (two argument) operators the left operand is always fully evaluated before the right operand.
There are three factors that influence the ultimate value of an expression in any algorithmic language, and they work in this order:
Precedence says that some operators bind more tightly than others.
Associativity is the tie-breaker for deciding the binding when we have several operators of equal precedence strung together. This only groups operands, does not say anything about the order in which they are evaluated.
The order of evaluation (if it is specified in a language) tells us the sequence, for each operator, in which the operands are evaluated. In java the order of evaluation is left to right, so after(i=2)*i++iis3after the expression, which evaluates to4(the left operand to the multiplication will be evaluated before the right operand, then the multiplication will be done, and theniwill be incremented).That is to say that i will be set to 2 first and 2 will be the value for the first operand in the multiplication. Then i++ will be evaluated for the second operand. This makes i 3 and 3 is the value returned for the second operand to *. The final result is 6, with i set to 3.
| Symbol | Note | Prec | Assoc |
|---|---|---|---|
| names, literals | simple tokens | 16 | n/a |
a[i]
| subscripting | 16 | left |
m( ... )
| method invocation | 16 | left |
.
| field selection | 16 | left |
++ --
| increment, decrement | 16 | right |
++ --
| increment, decrement | 15 | left |
~
| flip the bits of an integer | 14 | right |
!
| logical not (reverse a boolean) | 14 | right |
- +
| arithmetic negation, plus | 14 | right |
(typename)
| type conversion (cast) | 13 | right |
* / %
| multiplicative operators | 12 | left |
- +
| additive operators | 11 | left |
<< >> >>>
| left and right bitwise shift | 10 | left |
instanceof < <= > >=
| relational operators | 9 | left |
== !=
| equality operators | 8 | left |
&
| bitwise and | 7 | left |
^
| bitwise exclusive or | 6 | left |
|
| bitwise inclusive or | 5 | left |
&&
| conditional and | 4 | left |
||
| conditional or | 3 | left |
? :
| conditional operator | 2 | right |
= *= /= &=
+= -= <<= >>= >>>= &= ^= |=
| assignment operators | 1 | right |
3. Building Blocks
Primitive Types
There are 8 (eight) built-in, non-object types, also known as primitive types. They are discussed below:
boolean For truth values. Literals are:trueandfalse.
int, long, byte, short (for arithmetic on
integers) intis a 32-bit, signed, two's complement number (range of values is -232 to (232 - 1)).longis 64 bits,byteis 8 bits, andshortis 16 bits long.
double, float (for arithmetic on the real numbers) doublerefers to floating-point numbered stored in 64 bits.floatis on 32 bits.
char (for character data, ultimately to be input or printed) 16-bit unsigned quantity that is used to represent printable characters.Range of values: a value in the Unicode code set 0 to 65,535.
String is not a primitive type like the types described up to now in
this chapter. On the contrary, the type String is a type in Java, but
it is important enough to have support for it built into the language. Here's the
interface for String for your reference and information (taken from Flanagan):
public final class String extends Object implements Serializable {
// Public Constructors
public String();
public String(String value);
public String(char[] value);
public String(char[] value, int offset, int count);
# public String(byte[] ascii, int hibyte, int offset, int count);
# public String(byte[] ascii, int hibyte);
1.1 public String(byte[] bytes, int offset, int length, String enc)
throws UnsupportedEncodingException;
1.1 public String(byte[] bytes, String enc)
throws UnsupportedEncodingException;
1.1 public String(byte[] bytes, int offset, int length);
1.1 public String(byte[] bytes);
public String(StringBuffer buffer);
// Class Methods ------------------------------------------------------
public static String copyValueOf(char[] data, int offset, int count);
public static String copyValueOf(char[] data);
public static String valueOf(Object obj);
public static String valueOf(char[] data);
public static String valueOf(char[] data, int offset, int count);
public static String valueOf(boolean b);
public static String valueOf(char c);
public static String valueOf(int i);
public static String valueOf(long l);
public static String valueOf(float f);
public static String valueOf(double d);
// Public Instance Methods
public char charAt(int index);
public int compareTo(String anotherString);
public String concat(String str);
public boolean endsWith(String suffix);
public boolean equals(Object anObject); // Overrides Object.equals()
public boolean equalsIgnoreCase(String anotherString);
# public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin);
1.1 public byte[] getBytes(String enc) throws UnsupportedEncodingException;
1.1 public byte[] getBytes();
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin);
public int hashCode(); // Overrides Object.hashCode()
public int indexOf(int ch);
public int indexOf(int ch, int fromIndex);
public int indexOf(String str);
public int indexOf(String str, int fromIndex);
public native String intern();
public int lastIndexOf(int ch);
public int lastIndexOf(int ch, int fromIndex);
public int lastIndexOf(String str);
public int lastIndexOf(String str, int fromIndex);
public int length();
public boolean regionMatches(int toffset, String other,
int ooffset, int len);
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len);
public String replace(char oldChar, char newChar);
public boolean startsWith(String prefix, int toffset);
public boolean startsWith(String prefix);
public String substring(int beginIndex);
public String substring(int beginIndex, int endIndex);
public char[] toCharArray();
1.1 public String toLowerCase(Locale locale);
public String toLowerCase();
public String toString(); // Overrides Object.toString()
1.1 public String toUpperCase(Locale locale);
public String toUpperCase();
public String trim();
}
The Basic Statements
All statements in Java can be conveniently divided into four groups:
if ( Expression ) Statement [ else Statement ]
switch ( Expression ) {
case constant_1: Statement; break
case constant_2: Statement; break
...
case constant_n: Statement; break
default: Statement; break
}
for ( Initial ; Test ; Increment ) Statement
while ( Expression ) Statement
do Statement while ( Expression )
continue; continue Identifier;Here's an example:
months: for (int m=1; m <= 12; m++) {
// do something
// nested loop
for (int d=1; d <= 31; d++) {
// some daily thing
if (m == 2 && d == 28) continue months;
// otherwise something else
}
}
break; break Identifier;Example:
months: for (int m=1; m <= 12; m++) {
// do something
// nested loop
for (int d=1; d <= 31; d++) {
// some daily thing
if (m == 2 && d == 28) break months;
// otherwise something else
}
}
cost = 0;
return return Expression;
synchronize
The fourth one, are best described in the context of threads.
Objects
Java does not have pointers as they exist in C or C++. Pointers
in Java are called references. You can define linked lists in Java easily as
we have seen in hw #7.
The Object class and its methods.
public native int hashCode()
A hascode is an identifying value, ideally unique for every object in a program. A hashcode could be implemented as anything but in current compilers it looks a lot like an address. This and the next method go together.
public boolean equals(Object obj)
There are two philosophies for equality comparison -- something may have the same reference as what you're comparing it to ("is it at the same address?"), or it may have the same value ("are these bits here the same as those bits there?"). TheObjectversion of this method returnstruewhen the two objects being compared are actually the same one object. This is also the precise comparison of the==operator. However, you can overrideequalswith your own version, to give it a weaker definition. This has been done forStringbecause two strings are equal when they have the same characters. When you overrideequalsyou need to overridehashCodetoo, make certain that equalObjects get the same has codfe.
protected void finalize() throws Throwable
The method finalize() is just a hook you can override to help with memory management.
protected native Object clone()
throws CloneNotSupportedException Java supports the notion of cloning, meaning to get a complete bit-for-bit copy of an object. There are two kinds of cloning: shallow and deep.
public final native Class getClass()
Java maintains a run time representation for all classes (known as RTTI, for
"Run Time Type Identification"). This method gets that information (which is of
type Class, see below)
The Class class. The run time representation (or RTTI, for "Run Time Type Identification") is stored in objects whose class is calledOther built-in classesClass. The major use ofClassis to help with dynamically loading new classes. This is a systems programming activity unlikely to occur in your programs.
Basic type Corresponding class in java.lang boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double
Compilation Units
A source code is what you present to the Java compiler so that the contents of a complete source file are known as a "compilation unit".File Name is Related to Class NameAn important aspect is that Java has a
make-like utility built into it.
Java emphasizes the idea that the name of a file is related to its contents, and understanding this is the key to understanding how to build programs out of more than one file or library. A compilation unit (or source file) has several rules:
package statement, identifying
the package (a library) that the bytecodes will belong to. When starting
out it is simplest not to use packages. Your class files will be visible
to other classes in the same directory and belong to a default anonymous
package.
import statements, each identifying
a package or a class from a package that will be available in this compilation unit.
class declarations
and interface declarations. Interfaces are skeletons of classes showing
what form the class will take when someone implements it.
public. This class must
have the corresponding name as the file it is in.
The underlying host system should allow filenames with the same form as Java classnames.
At compilation time each of the classes in a .java file will create an individual
.class file to hold the generated byte codes.
Packages
The Java term package means a collection of individualThe CLASSPATH Variable.classfiles in a directory. So a package is both a directory and a library.
Is an environment variable, typically set in the
autoexec.bat file or in a shell initialization
file.
Import
You never have to use the import statement. Its effect is to allow you to use a class name directly, instead of fully qualifying it with the package name.
Visibility Issues
Four examples illustrating the interaction of public,
protected, default (package), and private.
We'll skip those for now, maybe I will present them later in separate
notes, referring exclusively to packages.
Interfaces
In languages with multiple inheritance names of methods sometime collide. For example if you had a
and aclass FlyingMachine
and both have aclass FloatingVessel
navigate method inside, what is going to inherit (if multiple inheritance were available).class Seaplane extends FlyingMachine, FloatingVessel
Which navigate
method,
FlyingMachine's or
FloatingVessel's?
interface FlyingMachine {
int navigate(Point from, Point to);
void land();
void takeoff(double fuel);
}
(The declarations in an interface are always public even if you don't
label them so.) An interface is thus a way of saying "you need to plug
some code in here for this thing to fully work". A later class implements
the interface by defining those methods including their bodies. If two
interfaces should happen to demand a method of the same name in a class
it isn't a problem. The implementation will define it(s meaning).
interface FloatingVessel {
int navigate(Point from, Point to);
void dropAnchor();
void WeighAnchor();
}
class SeaPlabe implements FloatingVessel, FlyingMachine {
// this is where we define the methods
// void dropAnchor()
// void weighAnchor()
// int navigate(Point from, Point to)
// void land()
// void takeoff(double fuel)
}
An interface differs from an abstract class in the following ways:
Once we have defined an interface, we can use it as the type of some parameter to a method. Inside the method we can use that parameter to invoke the operations that the interface promises. Whenever we make a call to that method, we can pass it a class that implements that interface, and it will call the approproate method of that class. The following four steps should make this a bit more clear:
run
like this: interface runnable {
public void run();
}
run throughout your code, even though we
don't yet have anything that fulfills the interface. This is one such place:
void vitalSystemThing(runnable r) {
r.run();
}
This code can be compiled and put in a library. class myCode implements runnable {
public void run() {
System.out.println("You called myCode.run()");
}
// ... other code
}
myCode to the vitalSystemThing:
This results invitalSystemThing(myCode)
myCode.run() being called back, hence this is known as a "callback".
We have described this when we looked at RMI (clients were able to register with a server and allowing it to notify them of subsequent developments).
This is a longwinded way of doing what you could do with a function pointer in C.
Note: the main reason for writing your code this way is that it decouples the calling
routine from the called back routine. You could have several different classes that
implement the runnable interface. Callbacks allow any one of them to be
sent to the vitalSystemThing and hence called back. The correct class is
called back based on the type at runtime.
4. Sample Techniques
Arrays
Java has neither the complexities nor the "size fixed at compile time" of C arrays. The Java array model is more like that of Ada: arrays of arbitrary bounds as parameters and dynamically-allocatable arrays each carrying around information about its own length.Arrays of ArraysIn some sense arrays are like objects:
- the language says so
- they are a reference type
- they are always allocated on the heap not on the stack
- inherit from
Objectand support methods such astoString()- are allocated with the
newoperatorOn the other hand arrays are not like objects in the following ways:
Examples:
- they have a different syntax from other object classes
- you can't subclass or extend arrays
- you can't define your own methods for arrays
- an array can't implement an interface or be cloned
int carrot[]; int carrot[] = new int[256]; a.legth // just a final data field so to speak
Examples:
or, create a triangular array of arrays and fill it with initial values:int cabbage[][];
int cabbage[][] = new int[5][];
int slice0[] = {0};
int slice1[] = {0, 1};
int slice2[] = {0, 1, 2};
int slice3[] = {0, 1, 2, 3};
int slice4[] = {0, 1, 2, 3, 4};
cabbage[0] = slice0;
cabbage[1] = slice1;
cabbage[2] = slice2;
cabbage[3] = slice3;
cabbage[4] = slice4;
that could be done in the following way too:
int cabbage[][] = { {0},
{0, 1},
{0, 1, 2},
{0, 1, 2, 3},
{0, 1, 2, 3, 4}
};
Exceptions
Exceptions are for changing the flow of control when some important or unexpected event, usually an error, has occurred. Exceptions are caused in one of two ways: the program does something illegal (usual case) or the program explicitely generates an exception by executing the throw statement (less usual case). Exceptions don't reduce the amount of work you have to do to handle errors, their advantage is that they let you collect it all in well-localized places of your program, so you don't obscure the main flow of control with zillions of checks of return values. The general form of how to catch an exception isThreadsSummary of exceptions:try block [ catch (arg) block ] [ finally block ]
- Purpose: safer programming by providing a distinct path to deal with errors
- Use them, they are a useful tool for organized error handling.
- The main use is getting a decent error message out explaining what failed and where and why. It's a bit much to expect recovery, graceful degradation is often the most you can obtain.
This topic has been thorougly treated in lecture 22Garbage Collection and Finalizers
Languages with dynamic data structures must have some way of telling the operating system that they need more memory, and conversely their run time system needs to have a way to indicate memory that is no longer in use. It is the job of a special runtime Java component, called the garbage collector to sit on top of the heap and periodically scan it to determine things that aren't being used any more. It can reclaim that memory and put it back in the free store pool within the program.5. An Example Program. UtilitiesThere is almost no direct interaction between the programmer and the garbage collector system.
A finalizer is a Java term related but not the same as a C++ destructor.
When there are no further references to an object its storage can be reclaimed by the garbage collector. A
finalizeris a method from classObjectthat any class may override. If a class has a finalizer method it will be called on dead instances of that class before the memory occupied by that object is reused.
Case Study Program
The Sorting Threads Applet by James Gosling
The listed program is using AWT 1.0.2 but is a good example of an applet that uses threads and graphical output to demonstrate the relative speeds of three different, but popular, sorting algorithms.
Utilities
java.util
BitSet Date Enumeration Hashtable Properties Random Stack StringTokenizer
The fundamental idea of StringTokenizer is to instantiate it with
a string and it will then break that string upm into islands of characters separated
by seas of white space.
In fact it acts like Perl's split so you can
specify the delimiters for the substring, and they don't have to be whitespace. One of
the constructors allows for new delimiting characters to be set and also takes a boolean
saying whether the delimiters themselves should be returned. The representative methods
are:
public StringTokenizer (String words_to_breakup); // constructor
public StringTokenizer (String words_to_breakup
String delimiting_chars,
boolean return_delims
); // also constructor
public boolean hasMoreTokens();
public String nextToken();
Vector Examples will be provided in future lab/lecture notes for those that have not been exemplified in past lecture/lab notes.
6. Applets
This part covered in first lecture and in the textbook. Only reminder here with class hierarchy.
Summary of Useful Methods in An Applet
| Method | Description |
|---|---|
void init() | Called when the applet is first loaded into memory. Typically you override it with one-time initialization code. |
void start() | Called each time the browser visits the page containing the applet. Typically you override it to start or resume any threads the applet contains. |
void paint(Graphics g) | Will be called by the window system when the component needs to be redisplayed. You will not call this. You will override this if you dynamically change the appearance of the screen, and what to see it appear. |
void stop() | Called when the browser leaves the page containing this applet. Typically you override it to stop or suspend any threads the applet contains. |
void run() | Nothing to do with applets. This is the main routine in which thread execution starts. |
java.applet.Applet
|
+-extends
java.awt.Panel
|
+-extends
java.awt.Container
|
+-extends
java.awt.Component -- implements
| java.awt.MenuContainer,
| java.awt.image.InageObserver,
| java.io.Serializable
+-extends
java.lang.Object
7. I/O and Networking
I/O in Java is highly modular. There are many classes that specialize in one kind of I/O. It is very easy to connect objects of these classes together (like a Unix pipe) so that as the data flows through they are modified or filtered in the way you need.
7.1 Interactive I/O
System.in - STDIN
System.out - STDOUT
System.err - STDERR
paint method
one can draw apublic void paint(Graphics g)
String by calling a routine that operates on the
Graphics object argument to paint:
g.drawString(some_string, x, y)
To input some text in an applet one would use a text widget (text area or text field). To read values from the keyboard in applications we use file i/o, as summarized below:
| Preliminary Declarations | |
|---|---|
import java.util.*; import java.io.*; static DataInputStream dis = new DataInputStream (System.in); static StringTokenizer st; | |
| Note: an exception handler declaration is also needed. | |
| Type | Code |
boolean |
st = new StringTokenizer(dis.readLine()); boolean bo = new Boolean(st.nextToken()).booleanValue(); |
char |
char ch=dis.readLine().charAt(0); |
int |
st = new StringTokenizer(dis.readLine()); int myint = Integer.parseInt(st.nextToken()); |
byte |
input as int and cast to byte
|
short |
input as int and cast to short
|
long |
st=new StringTokenizer(dis.readLine()); long mylong = Long.parseLong(st.nextToken()); |
float |
st = new StringTokenizer(dis.readLine()); float f = new Float(st.nextToken()).floatValue(); |
double |
st = new StringTokenizer(dis.readLine()); double d = new Double(st.nextToken()).doubleValue(); |
String |
String s = dis.readLine(); |
| Notes: |
try {
// put your I/O statements here
} catch (IOException ioe) {
ioe.printStackTrace();
}
|
Each statement or group of statements must have an exception handler wrapped around it. Or, the
method must declare that it throws an IOException
|
|
We're using methods from the class
on theDataInputStream
object.InputStream System.in
File I/O: Streams
Java I/O is built on Streams. A Stream in Java could be getting its bytes from (or sending them to) a file, a String, a socket on the net, an array in memory, the terminal etc. The Stream knows how to pull bytes out of each of these, although the programmer doesn't need to know.
An input stream is something that sends us a succession of bytes, and an output stream is something that we can send a series of bytes to.
A given Stream is device-independent, greatly reducing the range of library calls one need to memorize. For example in case of networking problems one could temporarily modify the socket stream to receive data from an in-memory array and then change it back when we have everything debugged.
Input Streams
FileInputStream Gets bytes from a file.
StringBufferInputStream Gets bytes from a StringBuffer.
ByteArrayInputStream Gets bytes from an array.
PipedInputStream Gets bytes from a pipe (a data structure that squirts bytes at you).
More detailed examples will have to be deferred.
Output Streams
FileOutputStream Writes bytes to a File.
ByteArrayOutputStream Puts bytes into its own temporary internal storage, for later retrieval.
PipedOutputStream Puts bytes into a pipe (just a data structure that drinks down bytes that you pour into it).
Layering Streams on Top of One Another
You can connect one Stream to another and the results is also a Stream. Each Stream in this chain has the chance to modify the data as it goes by. Streams can be layered on top of each other to provide filtered processing.
Filtered Input Streams The constructors of these filtered streams take a Stream as an argument and give back a filtered stream. Java provides the following filtered input streams:
FilteredOutputStreams
The constructors of these filtered streams take a Stream as an argument and give back a filtered stream. Java provides the following filtered output streams:
I/O Exceptions
Tha basic I/O related exceptions are:
FileNotFoundException
InterruptedIOException
UTFDataFormatError
EOFException
Random Access
The class RandomAccessFile allows the file pointer to be moved to arbitrary positions in the
file prior to reading or writing.
The File class.
A number of methods are available in the class File to provide information about a file or a directory:
Platform specific I/O (separators)
7.2 Networking with Java
Networking at heart is all about shifting bits from point A to point B. Usually we bundle the data bits into a packet with some more bits that say where they are to go. That, in a nutshell, is Internet Protocol, or IP. If we want to send more bits than will fit into a single packet, we can divide the bits into groups and send them in several successive packets. These are called User Datagrams.
User Datagrams can be sent across the Internet using UDP (the User Datagram Protocol), which relies on the Internet Protocol for addressing and routing. UDP is like going to the post office, sticking on a stamp, and dropping off the packet. IP is what the mail carrier does to route and deliver the packet. UDP is used by SNMP (Simple Network Management Protocol) and TFTP (Trivial File Transfer Protocol).
Just as when we send several pieces of postal mail to the same address, the packages might arrive in any order. Some of them might even be delayed, or even on occasion lost altogether. This is true for UDP too; you wave good-bye to the bits as they leave your workstation, and you have no idea when they will arrive where you sent them, or even if they did.
Uncertain delivery is equally undesirable for postal mail and for network bit streams. We deal
with the problem in the postal mail world (when the importance warrants the cost) by paying an
extra fee to register the mail and have the mail carrier collect and bring back a signature
acknowledging delivery. A similar protocol is used in the network work to guarantee reliable
delivery in the order in which the packets were sent. This protocol is known as Transmission
Control Protocol or TCP. Two applications that run on top of, or use, TCP are: FTP,
the File Transfer Protocol, and telnet.
TCP uses IP as its underlying protocol (just as UDP does) for routing and delivering the bits to the correct address. However, TCP is more like a phone call than a registered mail delivery, in that a real end-to-end connection is held open for the duration of the transmission session. It takes a while to set up this stream connection, and it costs more to assure reliable sequenced delivery, but often the cost is justified.
The access device at each end-point of a phone conversation is a telephone. The access object at each end-point of a TCP/IP session is a socket. Sockets started life as a way for two processors on the same Unix system to tslk to each other, but some smart programmers realized that they could be generalized into connection end-points between processes on different machines connected by a TCP/IP network.
Sockets can deliver fast and dirty using UDP (this is a datagram socket), or slower, fussier, and reliably using TCP (this is termed a stream socket). Sockets connections generally have a client end and a server end. Generally the server end just keeps listening for incoming requests ("operators are standing by" kind of thing). The client end initiates a connection, and then passes or requests information from the server.
What's in the Networking Library
InetAddress | The class that represents IP addreses and the operations on them. |
DatagramPacket | A class that represents a datagram packet containing packet data, packet length, internet addresses and port. Packets can be sent and received. |
DatagramSocket | This class allows datagrams to be sent and received using the UDP. |
PlainSocketImpl | This is the default socket implementation. It doesn't implement any security checks nor support firewals. |
SocketImpl | This is the Socket implementation class. It is an abstract class that must be subclassed to provide an actual implementation. The Unix Socket API does not distinguish between client and server sockets, but the Java API does. |
ServerSocket | The server Socket class. It uses a SocketImpl to implement the actual socket operations. It is done this way so that you can change socket implementations depending on the kind of firewall used. |
Socket | The client Socket class. It uses a SocketImpl to implement the actual socket operations. Agai, this permits you to change socket implementations depending on the kind of firewall that is used. |
URL | The class represents a Uniform Reference Locator - a reference to an object on the web. You can open an URL and retrieve the contents, or write to it. |
TCP/IP Client Server Model
Here's how a client and a server typically communicate over a TCP/IP network connection.
The processes contact each other by knowing the IP address and a port number. The IP address is like a telephone number, and a port number is like an extension at that number. Together they specify a unique destination. The client and server must agree on the same port number (just as for telephone calls).
For simplicity network socket connections are made to look like streams. You simply read and write data using the usual stream methods and it automagically appears at the other end. There's a method to get the input stream of a socket and a method to get the output stream. This allows the client and server to talk back and forth.
8. Utilities and Libraries Tentative Overview
Continues the portability goals of the language. Provides a single-windowing user interface ojn systems with wildly different native window systems. AWT 1.0.2 is covered here.
The Role of Objects
Method inheritance is a key part of the window interface in Java.
The basic components of a GUI (buttons, textfields, scroll bars, lists
and so on) are all created by subclassing the superclass called
Component.
9.1 How It Works
The AWT requires the native window system to be running on the platform, as it uses the native window system to implement windows within Java. The basic flow is this:
Windowing programs are asynchronous. Event-driven programming is used.
In the event-driven programming the program mostly waits for user input. When the user touches something on screen with the mouse pointer the window system catches the event and passes it on to a handler that you earlier supplied. This is known as a callback, and your handler is a "callback routine" because the window system calls back to it when the event happens. Your handler will deal with the graphics event, and the action that is associated with it.
Almost the whole of window programming is learning about the different objects that you can put on the screen (windows, scrollbars, buttons, etc.) Your event handling code for each widget will be invoked as needed.
Details of the AWT
The AWT provides five services to the programmer:
9.2 The Class Hierarchy
Component --+-- lots of widgets (described in section 9.3)
|
+-- Container -+- Panel ---- Applet
|
+- Window -+- Dialog
|
+- Frame
Components are the most general, kind of GUI object. They do two
principal things: ComponentWindow, which are separate pop-up windows in their own right
Panel (they generally represent a smaller part/area of a larger
Window).
A Few Words on Getting a GUI Event
- Component
- Everything on the screen is built out of Components.
- Container
- A data structure class that is used to hold several widgets, and treat them as a related group.
- Window
- This is a totally blank window.
- Frame
- Specialization of
Windowon which Menu bars are created and processed.- Dialog
- The
Dialogclass can be used to pop up a window that has an area where the user can type a line of text.- Panel
- A container with a built-in way to layout on the screen everything it contains.
- Applet
- A subclass of
Panel.
(This describes the 1.0 Event model in Java.)
Just as adding widgets to a panel or frame is easy, so is getting back user input. Everything hinges on the method with this signature:
The method is part of everypublic boolean action(Event e, Object o)
Component so all of the widgets inherit it
and can override it.
Whenever a user operates a Component (presses a button, clicks on a choice, etc), the
action event is called. The Event e argument contains much information
about the coordinates of the event, the time it occurred, and the kind of event that it
was. If the event was a keypress, it has the value of the key. The other argument is a
generalized object that contains extra information in some cases.
The event contains a field called id that indicates the type of event it is
(e.g., KEY_PRESS, MOUSE_DOWN, LIST_SELECT, etc), and hence which other Event variables are
relevant for the event. For keyboard events, the field called key will will contain
a value indicating the key that was pressed/released and the modifiers field will contain the modifiers
(whether the shift key was down, etc).
9.3 AWT Widgets
Sample code to create the widgets above in an applet will be provided here later.
9.4 Mouse and Keyboard Input
The previous section described how various widgets interact with the user. This section describes how mouse and keyboard events are passed to your program. It is done in a very similar way to what we have already seen for widgets.
Events go to the Component that is the immediate Container of the place where the event
happened. The class Component has a method handleEvent() with this signature:
This function is essentially a switch based on the type of event that occurred and factoring out the keyboard and mouse events calling individual methods to handle all possibilities.public boolean handleEvent(Event evt)
A list of some of the specific Event handlers that it factors out:
To see what's really going on with events, insert this line at the start
of your version of handleEvent:
System.err.println("Event: " + e.toString());
You will be amazed at the number of events that are generated by even the simplest mouse motions. This
method converts each such event to a string and then prints it. 9.5 Layout in a Container
The following layout managers can be used:
10. Graphics Programming
This chapter looks at how to draw shapes on a Canvas or
a Panel.
Table: Common Graphics Methods
This table lists the methods that cause the screen to be displayed.
| Method | Description |
|---|---|
void repaint() |
You or the window system may call this to request
that the window be refreshed. Typically, you would call it if you
have changed the appearance of something, and you want to see it on
the screen. It calls update()
|
void update(Graphics g) | This is a step in repainting the window. It defaults to clearing the area then painting it, but you can conceivably override it to do something additional. However, most of your programs will not override this, and will not call this. |
void paint(Graphics g) | Will be called by the window system when the component needs to be redisplayed. You will not call this. You will override this if you dynamically change the appearance of the screen, and want to see it appear. |
So When Do I Call These Methods?
If you just use the static display of a GUI you might never need to override any of the
three above methods. You can often just hide() and show() Components
as needed.
Normally the window system keeps track of what you have put on the screen. If you obscure it with other windows and then bring it to the front the window system is responsible for for restoring the state.
If you want to change what you have out on the screen
this would be accomplished by overriding paint(). Code in init() can
get something on the screen to begin with. Code in paint() can change the screen and
get something different up there. You call repaint() to signal to the window system
that it needs to update the screen. The window system will then call your paint()
method to put the new image on the screen. It's done this way because paint takes an argument
(a GRaphics context_ that you don't normally have (or need to have) access to. repaint()
doesn't need any arguments.
repaint() calls update() which calls clear() and then
paint(). You might override update() if you are doing some advanced graphics
work and you know that you only need a small portion of the screen to be changed (e.g., in animation).
update() gives you the opportunity to achieve this, by providing a point where you can
insert your own code between repaint() and paint(). In addition
will repaint just the stated size rectange at the given coordinates. Paint may be called by the runtime independent ofrepaint(x, y, w, h)
update.
Summary:
You never callpaint()yourself. You may override it, but the understanding is always that it will be called for you at the times the window system thinks it needs to update the screen. If you want to force the window system to think that, callrepaint().
repaint()simply lodges a request to update the screen, and returns immediately. Its effect is asynchronous, and if there are several paint requests outstanding it is possible that only the lastpaint()will be done.
10.1 Colors, Fonts
The basic color model is a common one in the computer industry.
Font Metrics
10.2 The Graphics Context
A Graphics object is what you ultimately draw lines, shapes and text on. It is also called a "graphics context" in some window system because it bundles together information about a drawable area, plus font, color, clipping region, and other situational factors.
It's an abstract class, so it cannot be instantiated directly.
The most common way to obtain a Graphics object is as the argument to a paint()
routine in a Canvas or a Panel.
Less commonly you can explicitly ask for the Graphics object belonging to any Component or any image with the call
When you callmyComponent mc = ... Graphics mg = mc.getGraphics();
getGRaphics is is usually for an Image, Panel, or Canvas. It's
unlikely you'll get the Graphics object for anything else, such as a button.
Drawing Text, Lines, and Shapes
Methods of Graphics that draw text, lines and shapes.
Most of them come in two varieties: a drawXXX and a fillXXX.
10.3 Images
Loading and Drawing Images in
10.4 Animation
If you have the frames it's easy.
12. Future Developments (or Where Do We Go From here? )