Professor Cullen Lecture Notes

COMS115 Introduction to Computer Science II


Topic 1
Review of Fundamentals


Definition:

Object-Oriented Programming Tenets

Inheritance means that a class can inherit all of the public or inheritable variables and methods from its parent class.  The inheriting class is a subclass of the parent or super class.  The child subclass program is said to "extend" its parent class.  The subclass can override the variables and methods of its parent or super class.  Inheritance provides programmers with the capability of efficiently reusing code.

 

Encapsulation is the concept of hiding the implementation details of a class and allowing access to the class through a public interface.  It allows a program to act as a  "black box". For this, we need to declare the instance variables of the class as private or protected. The client code should access only the public methods rather than accessing the data directly.  Also, the methods should follow the Java Bean's naming convention of get and set. Encapsulation makes the program modular and relatively easy to maintain and modify code. The client calling code is not affected when the internal implementation of the code changes as long as the public method signatures, that is the called entry points and their passed arguments remain unchanged.

 

Polymorphism with regards to JAVA programming means using the same method name in subclasses and letting the system handle the invocation of the correct method depending on the reference to the subclass.


Topic 2
Objects and Classes


Definition:

An Object represents an entity in the real world that can be distinctly identified, having state and a set of behaviors.

The state of an object is defined by data fields or variables, called properties along with their values, such as length, type and value.

The behaviors of an object is defined by the set of methods used by the object to perform a task or to manipulate the contents of its properties.  To call a method of some object is to ask the object to perform some work.

Classes are constructs that define objects of the same type.  A collection of properties (variables) and methods (procedures) for carrying out operations on their properties.  They provide a blueprint that define what an object's data and methods will be.  An object is a single instance of a class.

The process of constructing an instance of a class is called Instantiation.

 

Variables

Instance variables are bound to a particular instance of a class, and are therefore non-shared and unique.  Each variable is stored in a unique location of memory with its own address. Every object has its own set of variables.

Static variables are shared data variables.  They are not bound to any class.  The values for static variables are stored in a common memory location.  This property lends these variables useful as global variables.

 

Methods

Methods are procedures that optionally have a list of arguments passed to them.  The signature of a method is its name and the types and number of arguments in sequence that is passed.  Methods with the same name but different signatures (number or type of arguments) are said to "overload" each other.

 

Instantiation simply means to create an instance, a copy, of the "original blueprinted" class.  This entails the JVM acquiring virtual storage (GETMAINs), copying the methods and properties into that storage, and giving addressability of that storage block to the calling program.

 

Constructors are special methods used to construct or instantiate unique objects from a particular class.  They must have the same name as the defining class.  The constructor returns as its output a new instance of its class.

 

Instance methods are bound to a particular instance of a class, and are therefore unique.  Each method block of code is stored in a unique location of memory.    An instance method is invoked by specifying the instance name followed by a period and the method's name.

 

Static (or Class) methods are not bound to any class.  The code for static methods are stored in a common memory location.  A static method is invoked by specifying the class name followed by a period and the method's name. Calling programs share the static methods in a static class. A change to the variables of a static class is “seen” by all programs that use that class.

 

The Static Initializer is used whenever it is desired to perform some initial action only the first time the class is instantiated.  If all the properties and methods of a given class ABC are static and the constructor uses a static initializer, then only one copy of the class ABC can exist and it is initialized only once.

 

Example:

private NodePool()  { }

static {            // static initializer
    avail = 0;
    for (int i = 0; i < NUMNODES - 1; i++)
   {
         nodePool[i] = new Node(null, (i + 1));
    }
}  // end constructor

 

Primitive and Reference Variable Types
A primitive is a basic variable that defined and maintained by the language implementation. The primitive type holds the value of the primitive.   Such as int, long, and char.

 

A reference variable type refers to constructed object by programming on the language. It holds a reference pointer to where the object of that type is stored in virtual memory.

Example:    Rectangle  mySquare = new Rectangle(side_length);

This statement instantiates a new Rectangle object referenced as mySquare.

 

To access the basic Console I/O source code: Console.java,


Topic 3
Strings and Character Classes


Definition:

A String is a sequence of characters. Though Strings are actually arrays of characters, in JAVA Strings are treated as objects. They must be instantiated and therefore the string variables are reference variable types.

Strings must be constructed and are immutable. The value of a string is fixed at creation time.

 

Example: String greeting = new String("Hello World");

                char[] myCharArray = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
                String myGreeting = new String(myCharArray);

                String s = "This is a string";    //Defines a String s and refers to the data.

                s = "This is new data";    //Same String reference, different data.

 

String Comparisons

You must use the equals method of the String class to compare the contents of String objects.

Do NOT use the "==". This only checks as to whether strings1 and strings2 refer to the same object.

 

Example:    if (string1.equals(string2))
                    {
                            System.out.println("string1 and string2 have the same contents);
                    }

 

Strings methods include:  (s1 and s2 are String objects)

length:                s1.length();

concatenation:   String s3 = s1.concat(s2);
                           String s3 = s1 + s2;

extraction:          String s2 = s1.substring(start, end);
                           char x = s1.charAt(index);
 
comparison:       if (s1.equals(s2) == true)
                           if (s1.compareTo(s2) == 0)

scanned:             x = s1.indexOf(char, start);

trim spaces:        s1 = s2.trim();

translation:         s1 = s2.toLowerCase();
                           s2.toUpperCase();
 
replacement:      s1 = s2.replaceAll('oldstring', 'newstring');

conversion:        int x = Integer.parseInt(s1);

tokenizer:           String[] fields = s1.split(pattern);

numeric value     s2 = s1.valueOf(intx);
                           s2 = s1.valueOf(doubley)

 

 

StringBuilder/StringBuffer Class

A StringBuilder is a sequence of characters like String. StringBuilder is an object and therefore reference variable types.

A StringBuilder is mutable. You can add, insert or append new contents into a string buffer.

 

Example:    StringBuilder myString = new StringBuilder();

StringBuilder methods include:  (for below examples s1 and s2 are StringBuilder objects)

concatenation:   s1.append("Hello");

extraction:          s2 = s1.substring (start, end);
                            
deletion:             s2 = s1.delete ( startIndex, endIndex);

insertion:            s2 = s1.insert(offset,data);

length:                int x = s1.length();

reverse:              s1 = s2.reverse();
 
replacement:      s1 = s2.replaceAll ( 'oldstring', 'newstring');

conversion:        String str = s1.toString ();

trim:                    s2 = s1,trimToSize ();

insert char           s1.setCharAt (index, char);

subsetting            s2 = s1.substring (startIndex, endIndex);

 

 

The Character Class

JAVA provides a "wrapper" class for every primitive data type. One of these is Character.

You can create a Character object from a char value.

 

Example: Character ch1 = new Character ('a');

Character methods include:

comparison:       if (ch1.equals(ch2) == true)
                           if (ch1.compareTo(ch2) == 0)

The following are Static methods of the Character Class:

check digit:         boolean b = Character.isDigit(ch1);

check alpha:       boolean b = Character.isLetter(ch1);

translation:         ch2 = Character.toLowerCase(ch1);
                             ch2 = Character.toUpperCase(ch1);

 

String Example: stringman.java,

 

 


Topic 4
Exception Handling


Definition:

An Exception is an instance of a class derived from the JAVA class Throwable.  Exception handling is used to deal with execution errors that occur at runtime.  Exception handling separates error-handling code from normal operating program code.

 

JAVA give the opportunity for the programmer to catch this type of error when it occurs and to perform some specific action, such as terminating gracefully or perform some recovery action.

The JAVA construct called the try-catch block is used to enable the program to catch the error and to continue execution.  

If no exceptions arise during the execution of the try clause then the catch clause(s) are ignored.  

If an exception arises and there is no exception handler found in the upward percolation or chain of methods being called then the program will terminate and the environment will post an error message on the console.

 

The finally clause is used to execute code within the try block regardless of whether an exception occurs or is caught.  The code in the finally block is executed under ALL circumstances.

 

Throwing Exceptions
A program that detects an error can create an instance of an appropriate exception type and throw it back to the offender (the caller of  the routine).  An example such as below:

WrongArgumentException ex = new WrongArgumentException("Wrong Arg Received", arg[i]);
throw ex; 

OR

throw new WrongArgumentException("Wrong Arg Received", arg[i]);

 

Catching Exceptions
Code within a try block that catches, or is alerted to, any thrown exceptions and gracefully handles the exception.

try 
{
     some set of statements that may throw exceptions
}
catch (Exception1  exc_variable1)
{     handler for this exception}
    :
catch (ExceptionN  exc_variableN)
{     handler for this exception}

finally
{
      finalStatements; 
}

 

Defining your own Custom Exceptions
Should you encounter a problem that cannot be sufficiently described by one of the existing JAVA  predefined exception classes then you may create your own.  Your new class will become an extension of the Exception.class.

Example:

public class myException extends Exception
 {
    private int somenumber;
    private String somestring;

    public myException(String s, int n)
    {
        somenumber = n;
        somestring = s;
    }

    public String getMessage()
    {
        StringBuilder retstr = new StringBuilder(); 
        retstr = retstr.append("Some message ");
        retstr = retstr.append(somestring);
        retstr = retstr.append(" some more message ");
        retstr = retstr.append(somenumber);
        return retstr.toString();    
     }
}

Example: ExceptionLab.java, checkAlpha.java, AlphabeticException.java,


Topic 5
File Input/Output


Definition:

A File is an object that encapsulates the properties of a file or a path to a file, but does not contain methods for reading or writing or manipulating data in a file. In order to perform input and output (I/O) the file objects require other programmed objects to create, read and write file data.

 

To access the File class example: TestFileClass.java,

 

Text and Binary Files

Text files are in a human readable form. Also known as "clear text", its characters include the alphabet, numerals and special characters, such as those found on your computer keyboard. Text files are character oriented, strings of characters.

 

Binary files are not in human readable form and most characters on "not displayable". Binary files are bit oriented, strings of bits.

 

The design of the Java I/O classes represents a good example of applying inheritance, where common operations are generalized in parent or superclasses, and subclasses provide the specialized operations.

 

 

 

Text I/O

Reader and Writer are the root object classes of text input and output classes.

 

FileReader/FileWriter are convenience classes for reading/writing characters from/to files using the default character encoding on the host computer. Bytes are encoded and decoded to text for you.

 

BufferedReader/BufferedWriter is used to increase the performance of input and output by reducing the number or reads and writes required. Buffered streams employ an array of characters that acts as a cache or speed matching buffer.

 

Example:

BufferedReader filein = new BufferedReader(new FileReader("myinput.txt");
BufferedWriter fileout = new BufferedWriter(new FileWriter("myoutput.txt");

 

 

 

Binary I/O

InputStream and OutputStream are the root objects of binary input and output classes. Binary I/O does not requires encoding and decoding. When you write a byte of data to a file, the original byte is copies into the file unaltered. When you read a byte from a file, the exact byte in the file is returned.

 

FileInputStream/FileOutputStream classes are used for reading/writing bytes from/to files. Both inherit from InputStream/OutputStream respectively.

 

InputStreamReader/OutputStreamWriter classes are optionally used to convert between bytes and characters. If no encoding scheme is specified, the system's default encoding scheme is used. This class is used when you want to read and write in binary but process as text.

 

BufferedInputStream/BufferedOutputStream is used to increase the performance, like its text processing counterpart, of input and output by reducing the number or reads and writes required. Buffered streams employ an array of characters that acts as a cache or speed matching buffer.

 

 

Example of binary I/O:

BufferedInputStream filein = new BufferedInputStream(new FileInputStream("myinput.txt");
BufferedOutputStream fileout = new BufferedOutputStream(new FileOutputStream("myoutput.txt");

Example of binary I/O with text conversion:

BufferedInputStream filein = new BufferedInputStream(new InputStreamReader(new FileInputStream("myinput.txt");
BufferedOutputStream fileout = new BufferedOutputStream(new OutputStreamWriter(new FileOutputStream("myoutput.txt");

 

 

 

To access the text FileIO class example: FileIO.java, IOLab.java


Topic 6
Swing Windowing Tool


JAVA Graphical User Interface Basics

 

All components inherit from Object.

Object -->Component-->Container-->JComponent-->all Jxxxxx

 

JComponent is the superclass of all the Swing components.

 

Container classes are the GUI components that are used to contain other GUI components.

The two top-level containers are JFrame for handling windows on a local computer display, and JApplet for managing windows originating from a browser application. To create a user interface you need to create either a frame or an applet to hold the remaining user interface components.

JPanel is a container, but cannot be used as a top-level container.

 

All other containers must be placed in either a JFrame or JApplet or another JPanel container. JPanel supports double-buffering and can help eliminate display flicker.

 

The JScrollPane container is used to present a view for displaying contents that doe not fit completely into the viewing area.  It gives you horizontal and vertical scrollbars for moving the content view. 

We are interested in the containers of: JButton, JFrame, JTextField, JPanel and JScrollPane.

 

 A layout manager is a special object used to place and arrange UI components in a container in a particular fashion.  JAVA's layout managers provide a level of abstraction that automatically maps your user interface in all window systems.

We will be using the layout managers of: GridLayout, BorderLayout and FlowLayout.

 

 

Events and Listeners

When you run JAVA GUI programs, the program interacts with the user, and the events drive its execution. An event can be defined as a signal to the program that something has happened.  Events are triggered either by external user actions, such as mouse movements, button clicks and keystrokes, or by internal program activities such as a timer pop or message event.

 

A component on which an event is fired is called the source object. You can identify the source object of an event by using the getSource() method of the EventObject class.

 

A Listener is a program or handler that gets control when an interruption event takes place, such as a button being pushed or a window being activated.  The Listener's job is to process the event. 

The Listener object must be registered by the source object so that it gets control during the interruption event.

Component JButton requires that an ActionListener be employed to handle events of it being pushed.

Component JFrame windowing requires that an WindowListener also be employed to handle the events of window management such as closing, opening, activation, etc.

 

Applets

Applets are a short name for Application.  In particular, an application that is web-enabled and runs under a browser as opposed to your desktop.  The browser is the parent of the applet.

An applet is a special kind of Java program that a browser enabled with Java technology can download from the internet and run. An applet is typically embedded inside a web page and runs in the context of a browser. The Applet class provides the standard interface between the applet and the browser environment.

Swing provides a special subclass of the Applet class called javax.swing.JApplet. TheJApplet class should be used for all applets that use Swing components to construct their graphical user interfaces (GUIs).

 

 

Methods for Milestones

The JApplet class provides a framework for applet execution, defining methods that the system calls when milestones occur. Milestones are major events in an applet's life cycle. Most applets override some or all of these methods to respond appropriately to milestones.

init Method

The init method is useful for one-time initialization. The init method typically contains the code that you would normally put into a constructor.

start Method

Every applet that performs tasks after initialization (except in direct response to user actions) must override the start method. The start method starts the execution of the applet.

stop Method

Most applets that override the start should also override the stop method. The stop method should suspend the applet's execution, so that it doesn't take up system resources when the user isn't viewing the applet's page. For example, an applet that displays an animation should stop trying to draw the animation when the user isn't viewing it.

destroy Method

Called by the browser or appletviewer to inform this applet that it is being reclaimed and that it should destroy only resources that it has allocated.

 

Deploying an Applet

To deploy your applet, first compile the source code and package it as a JAR file.

Applets can be launched in three ways.  (These are beyond the scope of this course.  Please see the further detail documentation on SunMicrosystems’ website.)

·         You can launch an applet by specifying the applet's launch properties directly in the applet tag. This old way of deploying applets imposes severe security restrictions on the applet.

·         You can test your applet by using the appletviewer that calls the applets’ HTML file.

·         Alternatively, you can launch your applet by using Java Network Launch Protocol (JNLP). Applets launched by using JNLP have access to powerful JNLP APIs and extensions.

 

 

To access the frame example: myBorderLayout.java

To access the applet example: myApplet.java  myApplet.html

 

 


Topic 7
Multi-Threading


A Thread is the flow of a task's path of execution. A section of code that runs independently from its other threads.



Running multiple threads is like performing work from multiple separate “todo”lists. While the operating system may perform all the work on the lists in the correct order, it does not necessarily have to finish the work on one list before it works on another list. Some variable amount of work is performed from each list for an short interval of time. This period of execution is known as a “timeslice”. After a timeslice is consumed by the task thread, the operating system suspends (or preempts) the thread, then gives control to (or dispatches) some other thread. It continues to do this in “round robin” fashion until each thread has completed the work on its list.



An application program is said to be multi-threading if it spawns, or launches, two or more asynchronous concurrently or simultaneously running tasks, or threads of execution.

Tasks only communication with each other and the parent are through shared resources such as static virtual memory, shared disk areas, pipelines and sockets.

If you can interlace a program's CPU bound threads with its I/O bound threads then you can make your system perform better through greater efficiency. While one thread is waiting for I/O to complete, that other can make use of the CPU cycles.





Each new thread is an instance (or object) of a class that either:

(1) implements the Runnable interface directly or

(2) extends a class that implements the Runnable interface.  The object created is referred to a a RUNNABLE object.

The Thread class implements the interface Runnable, and by convention programmers extend the Thread class.

 

 

Thread States


New, when created.

Ready, after its start() method has been invoked from the dispatching thread. This in turn invokes the dispatched thread's run() method.

Running, when the thread is dispatched by the JVM, and while it is executing.

Blocked:
(a) Waiting to timeout; enqueued on a resource and waiting for either a time interval or resource to be freed.
(b) Waiting to be notified; enqueued on a resource and waiting indefinitely for the resource to become available.

Finished, when the thread returns from its run() method.



 

Interrupting a task / Checking for interrupts


The interrupt() method interrupts a thread.  If a thread is currently in the Ready or Running states, then its interrupted flag is set.  If the thread is currently in the Blocked state then a java.lang.InterruptedException is thrown, it is interrupted and it enters the Ready state.

The interrupted() method test whether this thread has been interrupted, AND resets the interrupted flag.

The isInterrupted() method test whether this thread has been interrupted, (does NOT reset the interrupted flag.)

 





Needs for Thread Synchronization


A Shared Resource will almost certainly become corrupted if it is accessed simultaneously or even concurrently by multiple program threads.

A race condition is an undesirable situation that occurs when multiple program threads attempt to perform operations at the same time on the same resource, but because of the nature of the system, the operations must be done in the proper sequence in order to be done correctly. Such as reading and updating a file. A program is said to be thread-safe if it does not cause a race condition in the presence of multiple threads.

Starvation occurs when one or more threads in your program are blocked from gaining access to a resource and, as a result, cannot make progress.

Deadlock, the ultimate form of starvation, occurs when two or more threads are waiting on a condition that cannot be satisfied. Deadlock most often occurs when two (or more) threads are each waiting for the other(s) to do something.

Livelock is a form of deadlock. It differs in that a competing threads repeatedly change their conditions without regard to the other threads. No progress is made because the meet in deadlock with another condition.

Indefinite Overtaking is a type of race condition. One or more fast tasks accessing a common resource with a relatively slow task(s). The slow tasks rarely get access to the resource because they are “overtaken” in processing speed by the faster tasks. By the time the slow task recycle themselves and attempt an access they are beaten to it by a faster task.

 



Synchronization Mechanisms

Two mechanisms used to ensure synchronization between threads is Enqueuing and Wait/Post.  

Enqueuing mechanisms are program constructs used for reserving a system resource. The resource can be virtually anything that can be shared between two or more tasks; such as static memory, a device, a data communications channel, etc.  Enqueueing is the process of attempting to acquire a lock on a resource, or waiting until the lock is available, locking the resource, performing some action on the resource, the releasing the resource and notifying other threads that the resource is available for locking.



Wait/Post mechanisms are program constructs used for synchronizing two or more threads (or tasks)  so that one task does not pass a particular point in its processing until the other(s) have reached an agreed upon point in their processing.   Such as waiting for all tasks to be fully initialized before having them attempt to send messages to each other.



Employing a synchronized method provides the programmer with a serialized way of locking a piece of programmed code for the duration of the method.  While within that method you can perform further programmed locks and employ enqueueing.

 

 

To access the class example:
MultiTaskingLab.java
myReaderTask.java
myWriterTask.java
myGlobals.java
myEnq.java



Topic 8
Networking


Client/Server Paradigm

Network programming involves a server and one or more clients.  The Server sits listening over a port or ports, and waits for a request of service to arrive from a client.

We will discuss both sides of the client/server relationship.

The Client initiates a request of the Server for some service by establishing a connection with the Server.

The Server accepts the connection and the request for service, performs the service and responds to the Client.



Sockets

The Server and Client communicate via Sockets.  

A Socket is a virtual communications channel connecting the two applications.  It is used for sending and receiving data.  A Socket is simply a software construct that represents one endpoint of a connection.  The Socket is constructed by an IP Address and a PORT pairing.

JAVA's socket-based communications enable application to view networking as if it were file I/O.  A program can read from a socket or write to a socket as simply as reading from a file or writing to a file.


The server socket is established using a call for an instance of ServerSocket, and telling it which Port on which it is to listen.

ServerSocket myserverSocket = new ServerSocket( portnumber );



The client socket is established using a call for an instance of a Socket referencing an IP Address and a Port upon which it will target a request to the server.

Socket myclientSocket = new Socket( serverName, portnumber );
or
Socket myclientSocket = new Socket( IP address, portnumber );



 

There are 65,536 possible logical ports available under TCP/IP.

Ports 0 through 1023 are reserved for conventional and restricted services.

Ports 1024 through 65,535 are available for any other uses.  


After the Server accepts the connection, communication between Server and Client is conducted the same as for all other I/O program streams.

InputStream input = socket.getInputStream();
OutputStream output = socket.getOutputStream():



Once communication is established, the protocol for  the ensuing conversation is a matter for the application.  The application protocol should define how data transfer is transmitted, primary and secondary roles,  receipt acknowledgement, synchronization, re-transmission, timeouts, and termination procedures.

To end the communication, each side should advise their communicating partner and then gracefully tear down the sockets.

 



More efficient Servers, known as multi-servers, will spawn off a thread to handle communications with each requesting Client, leaving the Server free to listen for more incoming requests for service from other clients. Each communicating client will cause the server to spawn another worker thread task to handle the call.



Servers and Clients can run on the same or different machines.

You can use the InetAddress Class to interrogate the client's host name and IP address.

inetAddress.getHostName()  and inetAddress.getHostAddress().

 



To access the class example: SocketLab.java pingGUI.java pongGUI.java

 


Topic 9
Asynchronous Task Communication


Static Global Variables

Global Variables are properties that can be shared by all tasks.  The tasks can read and update the same common variable.



Semaphores

Enqueueing allows 2 or more asynchronous tasks to compete to reserve an agreed upon common resource.

The Wait/Post facility allows taks to synchronize at a particular point in execution.



Sockets

Maintain a channel of communication between tasks.  The communicating tasks must check for data on some agreed and regular basis.



Interrupt Mechanisms

One task may interrupt another task if it has the reference to the object.  The Interrupted task can "see" the interruption and has the choice to schedule to "answer" that interruption.





To access the class example: sendME.java


 

[Return to Professor Page]