Source code of a Java program consists of one or more compilation units, implemented as files with .java extension.
|
Each compilation unit can contain:
-
a package statement
-
import statements
-
class declarations
-
interface declarations
|
Java compiler (called javac) reads java source and produces a set of binary bytecode files with .class extensions, one for each class declared in the source file. For example, if Foo.java implements Foo and Fred classes, then "javac Foo.java" will generate Foo.class and Fred.class files.
|
Suppose that Foo implements an applet and Fred is an auxiliary class used by Foo. If Netscape/Internet Explorer encounters a tag <APPLET code="Foo.class">, it will download Foo.class and Fred.class files and it will start interpreting bytecodes in Foo.class.
|
Each Java variable or expression has a definite type, given by a declaration such as"int i;". There are three "types" of types!
-
There are Primitive or Simple types such as integers or booleans which are built-in.
-
New composite types (objects) can be constructed in terms of classes and interfaces. The type of an object is its class or interface
-
Arrays we will see are a sort of "almost" object!
|
First we discuss the Primitive Types
-
There are 4 integer types: byte, short, int, long of size 8, 16, 32 and 64 bits, respectively.
-
float is 32 bits, double is 64 bits. Floating point arithmetic and data formats are defined by IEEE754 standard.
-
characters are given by 16bit Unicode charset and represented as short integers.
|
One can use casts for conversion such as longint = (long) i; // which can be explicit as here and sometimes implied (see later)
|
Note booleans are either TRUE or FALSE -- they are not 0, 1 ,-1 ...
|
Arrays are "true" or "first class" objects in Java and no pointer arithmetic is supported.
|
An Array is declared as:
|
alternative syntax: int[] vec;
|
and created by:
|
or concisely:
-
int vec[] = new int[128];
|
Arrays of arbitrary objects can be constructed,
-
e.g. Thread myThreadList[] = new Thread[1024];
-
The only difference is that in the case of primitive types, the array elements are actually allocated. In the case of arbitrary objects, an array of object references is created; before you use array elements, you must call the constructor of that type for each element.
|
Java's expressions are very similar to C and the following are valid:
|
2+3
|
(2+3)*i
|
i++ /* equivalent to i = i +1 */
|
(i > 0 ) && (j>0) /* Boolean */
|
i <<1 /* Left shift by 1 binary digit */
|
(i>0) ? true:false /* conditional expression */
|
i >>> 2 /* Signed right shift by 2 binary digits */
|
"fred" + "jim" is "fredjim"
|
/* + Equivalent to . in Perl */
|
(a instanceof B) /* True iff object a is of class B */
|
if(some boolean expression) { .. }
|
else if(another boolean) { .. }
|
else { ... }
|
while(any boolean) { /* Do Stuff */ }
|
do { /* What to do */ } while(another boolean);
|
for(expression1; booleanexpression ; expression2) { ...}
-
naturally starts with expression1, applies expression2 at end of each loop, and continues as long as booleanexpression true
|
switch (expression) { /* Just as in C */
|
case Constant1: /* Do following if expression=Constant1 */
|
/* Bunch of Stuff */
|
break;
|
case Constant2: /* Do following if expression=Constant2 */
|
/* Bunch of Stuff */
|
break; /* ....... */
|
default:
|
/* Bunch of Stuff */
|
break;
|
}
|
Programs are composed of a set of modules called classes. Each class is a template
|
specifying a set of behaviors on
|
the data of the class.
|
Each class has class variables
|
(sometimes called instance vars)
|
to hold the data and methods (called
|
functions or procedures in other
|
languages) to define the behaviors.
|
Each object in a program is created
|
as an instance of a class. Each class
|
instance has its own copy of the class
|
variables.
|
Classes can be used for data encapsulation, hiding the details of the data representation from the user of the class (by marking variables as private).
|
Casting (type conversion) is supported between types and class types. Syntax:
|
Two forms of casting are possible: widening and narrowing
|
Widening, where the subclass is used as an instance of the superclass, is performed implicitly
|
Narrowing, where the superclass is used as an instance of the subclass, must be performed explicitly
|
Given Parent: Dot -> DrawableDot (Child):
-
Widening: An instance of DrawableDot is used as an instance of Dot
-
Narrowing: An instance of Dot is used as an instance of DrawableDot
|
Casting between sibling classes is a compile-time error
|
Many languages are confusing as they differ in often unstated distinction between the value and "handle" -- Java is no exception! (reference,address,pointer) of an entity
|
Consider assignment: a = b; // sets value of a to value of b
|
If a and b are primitive types, then they hold "actual literals" and so if b=66, then a is set to 66
-
In this case if you change b, then a is left unchanged
|
However if a or b is an object, b is in fact a reference and so one sets a to refer to same object as b (i.e. same "location" in memory)
-
if you change b in some way, then a will be changed accordingly
-
Note null is value of an object which has not been assigned (constructed) and so does not point anywhere
|
Arguments to Methods are always passed by value BUT if an object is an argument, then that value is ALWAYS a reference and so in practice
-
Primitive types are passed by value
-
Objects are passed by reference
|
Arrays reflect properties of what they are arrays of!
|
Interfaces are either public or have the default friendly access (public for the package and private elsewhere)
|
Methods in an interface are always abstract and have the same access as the interface. No other modifiers may be applied
|
Variables in an interface are public, static, and final. They must be initialized.
|
When a class implements an interface:
-
it implements all the methods described in the interface
-
or it is an abstract class, which leaves the implementation of some or all of the interface methods to its subclasses
|
Interfaces can incorporate one or more other interfaces, using the extends keyword:
-
public interface DoesItAll extends Storable, Paintable {
-
public abstract void doesSomethingElse();
-
}
|
A class can implement more than one interface:
-
public class Picture implements Storable, Paintable {
-
public void store(Stream s) {...}
-
public void retrieve(Stream s) {...}
-
public void refresh() {...}
-
}
|
One conveniently uses files in a package by inserting
|
at the beginning of a file that needs classes from the mill package
-
Then classes in the mill package can be refered to by just using their Classname
-
Without the import command, one must explicitly say mill.Classname
|
Packages can be grouped hierarchically, with the corresponding directory tree. For example, the mill package could be a subpackage of agriculture. Then a class is referred to as agriculture.mill.Classname.
|
Except for classes provided with the Java language, all of which have the form java.X, a class that is imported or used must either be in the current directory or be accessible to the compiler through the CLASSPATH environment variable.
|
java.lang Contains essential Java classes and is by default imported into every Java file and so import java.lang.* is unnecessary. Thread, Math, Object and Type Wrappers are here
|
java.io contains classes to do I/O. This is not necessary (or even allowed!) for applets which can't do much I/O in Netscape!
|
java.util contains various utility classes that didn't make it to java.lang. Date is here as are hashtables
|
java.net contains classes to do network applications. This will be important for any distributed applications
|
java.applet has the classes needed to support applets
|
java.awt has the classes to support windowing -- The Abstract Windows Toolkit
|
java.awt.image has image processing classes
|
java.awt.peer is a secret set of classes with platform dependent details
|
When writing a Java applet, your code is overriding one of the standard applet methods, and you are not allowed to throw any exceptions that it would not. So, in general, you must handle exceptions.
|
What to do: The standard trick of writing a message to System.out works fine for debugging when running with the applet viewer. It also works fine with the Netscape browser for errors that you don't really expect to happen in working code (like your code had a null pointer) because Netscape provides a "Java console" under the Options menu that displays all messages.
|
However, for errors that you really want to bring to the attention of the user, such as they typed in their URL incorrectly and the network methods returned a "malformedURLException", you can put up a pop-up window in the style of professional GUI programs.
|
Note that you don't have to micromanage exceptions - you don't have to put a "try-catch" construct around every statement that can throw an exception. You can put the "try-catch" around the entire code with the same catch action or even put different catches for different actions of the errors.
|