Professor Cullen Lecture Notes

COMS145 JAVA Programming


Week 1
Fundamentals


Definition:

Introduction to Programs and JAVA

Memory is an ordered sequence of bytes that is used to store data and program instructions for the central processing unit (CPU) to execute.  A program and its data must be brought into memory, usually from an external storage device, before it can be executed.  Every byte of memory has an unique address.  This address is used by the CPU to locate the data for storing and retrieving the information contained in that byte.  Memory is volatile.

Storage Devices are devices where programs and data are permanently stored and moved into memory when called for by the CPU.  Some storage devices are hard disk, DVD, solid state flash-memory sticks and tapes.

An Input Device is one which accepts data for processing to the computer.

An Output Device is one which outputs results from the computer. 

A Program is a set of exact instructions for a computer to carry out.  Also known as software.

Machine Language is a set of primitive instructions in the form of binary code that instruct the computer.  Extremely hard for humans to read, but extremely rapid execution for the computer.

Assembly Language  is a low-level programming language in which primitive mnemonic codes are used to represent machine language.  Difficult for humans to read or write.  But after the assembly language is translated via an assembler into machine language it runs extremely fast on the computer.

High-Level Languages such as COBOL, JAVA, REXX and C++ are English-like and much easier to learn and used to program. 

A program written in this language form is called the source program.  

(a)  If the source program is translated by a compiler to produce an object program, then it is called a compiled language.  The object program is in machine language.  Object programs are linked together via the linkage editor to create an executable machine language program.  Compiled languages include COBOL, FORTRAN, and C++ 

(b)  If the source program, may or may not require a compilation process, but is further translated at run time by an interpreter into executable machine language, then it is called an interpreted language.  Intrepreted languages include REXX, Shell Script and JAVA.

The JAVA language programs are compiled into an architecture neutral "bytecodes".  These bytecodes will run on any computer with a Java Virtual Machine (JVM) installed.  The bytecodes are interpreted by the JVM into executable native machine code.  This is the feature that makes JAVA portable across all operating platforms.  "Write Once, Run Everywhere".

JAVA Language Specification:
API consist of the Application Programming Interfaces and the documentation on their use.

JDK is the JAVA Development Kit that supports compilation and execution, and contains a wealth of pre-compiled class libraries.

IDE is the Integrated Development Environment, such as SunMicrosystems NetBeans, it is used to create, compile and execute programs from scratch.

Structure of a JAVA program
Reserved Words are words that denote a specific meaning to the compiler and cannot be used for other purposes in your program.

Comments are used to help programmers communicate information regarding the logic and to help remember what the code actually does.

Classes are the essential JAVA constructs which encapsulates the program and their routines.

Statements are lines of code, terminated by a semicolon, that performs some action or work. 

Methods are a procedural set of instructions or statements, a routine, that may take arguments and performs some work and may produce a returned result.

Properties are definitions of data which include its type and number of storage bytes allocated.

Blocks are used to group components of a program.  A block is delimited by braces {}.  Every method employs a method block that groups the statements in the method. 

The main method defines where the control of flow for a JAVA program begins.  The JVM executes the application by invoking the main method.

Modifiers
JAVA uses certain reserved words called modifiers that specify the properties of the classes, methods and data as to how they can be used.

                  Visibility   Scope   Return_Type   MethodName  (Argument_List)                   

Examples:   public  static  void   main(String[] args)

                  private int  myroutine(String[] args, int, String, float) 


Week 2
Language Definition


Definition:

Data Types in JAVA

JAVA is a strongly typed language meaning that every defined variable must have a declared type.  There are eight primitive variable types in JAVA.

Integer Types
byte        1 byte          -2**7 through 2**7
short       2 bytes        -2**15 through 2**15
int           4 bytes        -2**31 through 2**31
long         8 bytes        -2**63 through 2**63

Note that each bit, except for the leftmost bit, represents a numerical power of 2.  The leftmost bit may represent a sign of negative or positive.  The initial definition of the variable must include the type.   Referencing a defined variable does not require using the type. 

Examples:
int mynumber = 10;

int aSmallNumber;

long myBigNumber = 987453627

Floating-Point Types
float        4 bytes (32bits)        +- 2**1023            +-2**(-1074)        7 significant decimal digits
double    8 bytes (64bits)        +- 2**1023            +-2**(-1074)       15 significant decimal digits

Examples:
float  mySinglePrecisionNumber = 456.987;
double myDoublePrecisionNum = 456.1234567892;

Character Type
In JAVA the char type represents a single character.  It describes a code unit in the UTF-16 encoding.  Unicode code units can be expressed as hexadecimal values that run from \u0000  to  \uFFFF.  Try to avoid the use of char type in your programs unless you are manipulating UTF-16 code units;  and strive to use "strings" for storage and manipulation of character data.

Special characters that we will use:
\n    LINEFEED
\r    CARRIAGE RETURN
\\    BACKSLASH

boolean Type
The boolean data type comes can have one of two values, true and false.  It is used for evaluating logical conditions.  This is the smallest amount of storage that any variable can use and hold a value.  The boolean variable requires 1 bit of storage into which the value 1 (true) or 0 (false) is loaded.

Examples:
boolean flag = false;
boolean semaphoreA = true';

Operators
Addition    +
Subtraction    -
Multiplication     *
Division     /                            Modulus (remainder)    %
Increment/Decrement    ++ and --   (used before or following the variable)
Relational    ==  (EQUALS)        !=  (NOT EQUALS)      <    >    <=    >=   
Logical Connectors    &&  (AND)       ||  (OR)
Negation    !    (NOT)
Ternary    ?            condition  ?  expressionA  :  expressionB

Do not confuse the "=" sign which means assignment with the "==" sign which means exactly equal to.

Simple Math Functions
y = Math.sqrt(x);
y = Math.pow(x, a);
y = Math.sin(x);
y = Math.cos(x);
y = Math.tan(x);
y = Math.exp(x);
y = Math.log(x);
y = Math.PI;
y = Math.E;

Strings 
Strings are sequences of Unicode characters.  The String is not a JAVA primitive but a predefined JAVA  class.  Each string is an instance of the String class.  Strings are immutable, that means that they are not changeable.

Unreferenced strings are automatically "garbage collected" by the JAVA Virtual Machine.

Example:
String msg = "The mouse ran up the clock";

Converting Strings to Integers
To convert a numeric string into an int value use the parseInt method of the Integer class.
Example:
int myint = Integer.parseInt(mystring);

Discussion on JAVA floating-point numbers (FYI only***)

A floating-point number has four parts -- a sign, a mantissa, a radix, and an exponent. The sign is either a 1 or -1. The mantissa, always a positive number, holds the significant digits of the floating-point number. The exponent indicates the positive or negative power of the radix that the mantissa and sign should be multiplied by. The four components are combined as follows to get the floating-point value:

sign * mantissa * radix exponent

Floating-point numbers have multiple representations, because one can always multiply the mantissa of any floating-point number by some power of the radix and change the exponent to get the original number. For example, the number -5 can be represented equally by any of the following forms in radix 10:

Forms of -5
Sign Mantissa Radix exponent
-1 50 10 -1
-1 5 10 0
-1 0.5 10 1
-1 0.05 10 2

For each floating-point number there is one representation that is said to be normalized. A floating-point number is normalized if its mantissa is within the range defined by the following relation:

1/radix <= mantissa < 1

A normalized radix 10 floating-point number has its decimal point just to the left of the first non-zero digit in the mantissa. The normalized floating-point representation of -5 is -1 * 0.5 * 10 1. In other words, a normalized floating-point number's mantissa has no non-zero digits to the left of the decimal point and a non-zero digit just to the right of the decimal point. Any floating-point number that doesn't fit into this category is said to be denormalized. Note that the number zero has no normalized representation, because it has no non-zero digit to put just to the right of the decimal point. "Why be normalized?" is a common exclamation among zeros.

Floating-point numbers in the JVM use a radix of two. Floating-point numbers in the JVM, therefore, have the following form:

sign * mantissa * 2 exponent

The mantissa of a floating-point number in the JVM is expressed as a binary number. A normalized mantissa has its binary point (the base-two equivalent of a decimal point) just to the left of the most significant non-zero digit. Because the binary number system has just two digits -- zero and one -- the most significant digit of a normalized mantissa is always a one.

The most significant bit of a float or double is its sign bit. The mantissa occupies the 23 least significant bits of a float and the 52 least significant bits of a double. The exponent, 8 bits in a float and 11 bits in a double, sits between the sign and mantissa. The format of a float is shown below. The sign bit is shown as an "s," the exponent bits are shown as "e," and the mantissa bits are shown as "m":

Bit layout of Java float
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

A sign bit of zero indicates a positive number and a sign bit of one indicates a negative number. The mantissa is always interpreted as a positive base-two number. It is not a twos-complement number. If the sign bit is one, the floating-point value is negative, but the mantissa is still interpreted as a positive number that must be multiplied by -1.

The exponent field is interpreted in one of three ways. An exponent of all ones indicates the floating-point number has one of the special values of plus or minus infinity, or "not a number" (NaN). NaN is the result of certain operations, such as the division of zero by zero. An exponent of all zeros indicates a denormalized floating-point number. Any other exponent indicates a normalized floating-point number.

The mantissa contains one extra bit of precision beyond those that appear in the mantissa bits. The mantissa of a float, which occupies only 23 bits, has 24 bits of precision. The mantissa of a double, which occupies 52 bits, has 53 bits of precision. The most significant mantissa bit is predictable, and is therefore not included, because the exponent of floating-point numbers in the JVM indicates whether or not the number is normalized. If the exponent is all zeros, the floating-point number is denormalized and the most significant bit of the mantissa is known to be a zero. Otherwise, the floating-point number is normalized and the most significant bit of the mantissa is known to be one.

The JVM throws no exceptions as a result of any floating-point operations. Special values, such as positive and negative infinity or NaN, are returned as the result of suspicious operations such as division by zero. An exponent of all ones indicates a special floating-point value. An exponent of all ones with a mantissa whose bits are all zero indicates an infinity. The sign of the infinity is indicated by the sign bit. An exponent of all ones with any other mantissa is interpreted to mean "not a number" (NaN). The JVM always produces the same mantissa for NaN, which is all zeros except for the most significant mantissa bit that appears in the number. These values are shown for a float below:

Special float values
Value Float bits (sign exponent mantissa)
+Infinity 0 11111111 00000000000000000000000
-Infinity 1 11111111 00000000000000000000000
NaN 1 11111111 10000000000000000000000

Exponents that are neither all ones nor all zeros indicate the power of two by which to multiply the normalized mantissa. The power of two can be determined by interpreting the exponent bits as a positive number, and then subtracting a bias from the positive number. For a float, the bias is 126. For a double, the bias is 1023. For example, an exponent field in a float of 00000001 yields a power of two by subtracting the bias (126) from the exponent field interpreted as a positive integer (1). The power of two, therefore, is 1 - 126, which is -125. This is the smallest possible power of two for a float. At the other extreme, an exponent field of 11111110 yields a power of two of (254 - 126) or 128. The number 128 is the largest power of two available to a float. Several examples of normalized floats are shown in the following table:

Normalized float values
Value Float bits (sign exponent mantissa) Unbiased exponent
Largest positive (finite) float 0 11111110 11111111111111111111111 128
Largest negative (finite) float 1 11111110 11111111111111111111111 128
Smallest normalized float 1 00000001 00000000000000000000000 -125
Pi 0 10000000 10010010000111111011011 2

An exponent of all zeros indicates the mantissa is denormalized, which means the unstated leading bit is a zero instead of a one. The power of two in this case is the same as the lowest power of two available to a normalized mantissa. For the float, this is -125. This means that normalized mantissas multiplied by two raised to the power of -125 have an exponent field of 00000001, while denormalized mantissas multiplied by two raised to the power of -125 have an exponent field of 00000000. The allowance for denormalized numbers at the bottom end of the range of exponents supports gradual underflow. If the lowest exponent was instead used to represent a normalized number, underflow to zero would occur for larger numbers. In other words, leaving the lowest exponent for denormalized numbers allows smaller numbers to be represented. The smaller denormalized numbers have fewer bits of precision than normalized numbers, but this is preferable to underflowing to zero as soon as the exponent reaches its minimum normalized value.

Denormalized float values
Value Float bits (sign exponent mantissa)
Smallest positive (non-zero) float 0 00000000 00000000000000000000001
Smallest negative (non-zero) float 1 00000000 00000000000000000000001
Largest denormalized float 1 00000000 11111111111111111111111
Positive zero 0 00000000 00000000000000000000000
Negative zero 1 00000000 00000000000000000000000



Week 3
Console Input/Output


Definition:

Standard Out  is the output that is normally directed to the terminal console.

Standard In  is the input that is normally read from the terminal keyboard.

Standard Err  is the error message output that is normally sent to the terminal console.

More on Strings
String is a predefined JAVA class in the standard JAVA library.

Substrings are subsets of some defined String.  Substrings themselves are Strings.

Strings can be concatenated by joining them with a "+" sign.

Testing strings for equality can be done using String's "equals" or "equalsIgnoreCase" methods.

The "trim" method returns a new string without the leading and trailing spaces.

Data Input
Console class, used by most pre- JDK 5.0 programmers, will read input from the terminal console window. one character at a time to form a string.

Scanner class, new with JDK 5.0, will read input from the terminal console window.

JOptionPane class, using the showInputDialog method, will put up an input window to enter the input you wish read along with a prompt.

Data Output
System.out.println which is the "println" method of the "PrintStream" class called by the "out" field property of the static "System" class is the standard way to write data to the terminal console followed by carriage return/linefeed character to cause a blank line following the outputted data.

System.out.printf which is the "printf" method of the "PrintStream" class called by the "out" field property of the static "System" class is the new JDK 5.0 opting to put data to the terminal console with formatting.



Week 4
Exception Handling and Flow Control


Definition:

Exceptions  are events that occur during the execution of a program and may disrupt the normal flow of control.  A program that does not provide logic for handling exceptions may abnormally terminate, causing problems for the user.  JAVA provides programmers with the capability to handle runtime errors.  This is referred to as exception handling

Possible errors can be caught by using the try-catch[-finally] block construct.  This allows the exceptions to be handled programmatically, prevent "ugly" messages to the user and permit execution to continue.  If an exception occurs within the try clause then the remainder of the lines in the try clause are skipped and the control is then transferred to the catch clause.  After the exception is caught and processed, control is transferred to the finally clause, if there is one, or to the next statement after the try-catch block.

If you as a programmer do not catch the exception, the JVM will and put out an ugly message(s) for your users, then terminate execution.

Prototype:    try
                    {
                    some set of statements, on of which you expect may throw an exception;
                    }  // end of try clause
                    catch
                        {
                       statements that handle the exception event;
                        }  // end of catch clause
                    finally
                        {
                        some set of statements that will always execute, exception or no;
                        } // end of finally clause

                    The next statement following try-catch-[finally] block

Example:    String s = null;
                  try
                    {
                    System.out.println("The contents of string s is " + s.toString() );
                    }
                    catch (NullPointerException exc)
                       {
                        System.out.println("Error, string s is NULL " + exc.getMessage());
                        }
                    finally
                        {
                        s = "ABC";
                        }
                    System.out.println("The contents of string s is " + s);      

JAVA has 3 classes of exceptions: 
system errors are thrown by the JVM and describe internal system errors

exceptions describes errors caused by your program and external circumstances.  These should be caught and handled by your program.

runtime exceptions are those that describe programming errors, such as bad casting, accessing an out of bounds array and numeric errors.  They are generally thrown by the JVM.

If an exception occurs that is caught by your program's catch statement, then the particular exception class is instantiated and can be referenced by the variable name you assign to the exception.  Using this instance variable you can call on its method "getMessage()" to obtain information regarding the cause of the exception.

Example:    System.out.println("An error occurred, information received is: " + exc.getMessage() );

Flow Control

Program flow control concerns itself with the order in which statments are executed in a program.  Most programming does not execute its statements in sequence.  Often situations occur in which you must provide alternate instruction paths.

If-then-Else Statement
This statement allows you to take actions when a condition is true and alternative actions when the condition is false.

Prototype:    if (boolean_expression)
                        {
                        statements for when condition is true;
                         }
                    else
                        {
                        statements for when condition is not true;
                        } 

Example:      boolean starsAreOut = false;
                    if (starsAreOut)
                        {
                        System.out.println("It is daytime.");
                         }
                    else
                        {
                        System.out.println("It is night.");
                        }

Nested If 
The statement in an if can be any legal JAVA statements including another if or if...else.  The inner if statements are said to be "nested".  There is no limit to the depth of nesting,  but after a few it does make it difficult to match up your IF and ELSE statements.



Week 5
Loops and Flow Control


Definition:

The SWITCH

SWITCH  statements are employed when nested IF-ELSE statements would make a program difficult to read and interpret by the human programmer.  The SWITCH statment will handle multiple conditions efficiently and may make it easier to program and debug.

Prototype:  switch (expression) {
                    case value1:    stmts;
                                  break;
                    case value2:    stmts;
                                    break;
                    case value3:    stmts;
                                    break;
                    case value N:    stmts;
                                    break;
                    default:    stmts;
                }

The "switch" statement will check all cases and execute beginning at the statement in the matched case.  It will execute or "fall-through" all remaining statements unless there occurs a "break;" statement. 

The switch "expression" must yield a value of char, byte, short or int type.  The "value" must have the same data type as that yielded by the switch "expression".

LOOP Statements

Loops are constructs that control repeated iterated executions of a block of statement code.  Each loop contains a loop continuation condition that controls the execution.  Prior to each iteration the loop continuation condition is re-evaluated.  If the condition is true, then the execution continues, if the condition is false then the loop terminates and passes control to the next statement outside of the loop.

There are three types of loop in JAVA:  while, do-while and for      

while loop

while (continuation_condition_is_true
{
    statements;
}

for loop

for (initial_value;  continuation_condition_is_true;  action_after_each_iteration
{
    statements;
}

Nested loops are loop constructs within loop constructs.  The nested loop appear to the outer loop as a statement to be executed independently. 

 Any loop can be terminated early by way of the break statement.  The break statement issued in an inner loop will cause execution to continue with the next statement in the set of statements being performed by the outer loop. 

Any iteration within a loop can be terminated early by way of the continue statement.  The continue statement will cause a pre-empting of any further statements in this iteration of the loop and continue the loop with the next iteration.

Nested for loop

for (initial_value_a;  continuation_condition_is_true;  action_after_each_iteration
{
    statements;
        for (initial_value_b;  continuation_condition_is_true;  action_after_each_iteration
         {
         statements;
         statements;
         break;  (or continue;)
         }
    statements;
}


Week 6
Calling Subroutines and Transfer of Control


Definition:

Calling a Method 

In creating a subroutine, you give a definition of what the routine is to do.  To employ the subroutine you have to call or invoke it by way of a method call.  The subroutine must reside in either this class or another class which your program has access to via packaging or import statment.  There are two ways to call a subroutine; the choice is based on whether the method returns a value or not.

If the method returns a value it is called a function.

Example:    int root = Math.sqrt(196);

If the method returns no value it is known as a void method or  a procedure.

Example:    System.out.println("Hello World"); 

Method Prototype Definition:
modifier  return_value  method_name(formal parameters)

Example:    public  int  mySubroutine(int arg1, int arg2, String arg3, double arg4)

Prototype for Invoking a method:
type result = method_name(formal parameters);

Example:    int rc = mySubroutine(arg1, arg2, arg3, arg4);

Transfer of Control
When one program calls a method, program control is transferred to the called method.  A called method returns control to the caller when its return statement is executed.

Passed Arguments
Each argument, if any, in the calling statement are matched positionally with arguments in the called method.  The corresponding arguments must match by type and order.  All arguments are passed by value, changes made to the variable in the called method do not affect the variable in the calling method.

Results
The result passed by the called method back to the calling method must be of the same type.  The result is placed as a variable or a literal in the return statment.

Method Overloading
If two or more methods have the same name but different parameter lists, the JAVA compiler determines which method is used based upon the "method signature".  This is called "overloading".

Scope of Variables
The scope of a variable is the part of the program where the variable can be referenced.  A variable defined inside a method is referred to as "local".  The scope of a local variable starts from its declaration and continues to the end of the code block that contains the variable.

A variable that is defined outside of all methods but within the class is called "global" to all in-class methods.  

Method Abstraction
Method Abstraction is a concept that is achieved by separating the use of a method from its implementation.  The user can call a method from some class without any knowledge of how it is implemented.   The details of the implementation are contained in the method and hidden from the client who invokes the method.  The user simply invokes the method passing the arguments required and expects a certain type of result to be returned.  This "black box" programming is known as encapsulation.  Of course, for encapsulated routines to be understood they must be well documented.


Week 9
Arrays


Definition:

An Array is a fixed-size sequential collection of elements of identical types.  In JAVA they are defined to be of some fixed immutable number of elements.  During allocation the array size must be given to specify the number of elements that can be stored in it.

Prototype for Declaring an array:
datatype[] ArrayReferenceName;

Example:    String[] myArray;

Prototype for Creating an array:
ArrayReferenceName = new datatype[number_of_elements];

Example:    myArray = new String[100];

Prototype for Declaring and Creating an array in one step:
datatype[] ArrayReferenceName = new datatype[number_of_elements];

Example:    String[] myArray = new String[100];

FYI: While the array variable appears to hold an array, it actually contains just a reference to that array.  The array variable and the array are different.

Initial Storage Contents

When an array is created its elements are initialized with the value of ZERO if the data type is defined as numeric.

If the array data type is defined as String or char then it is filled with unicode '\u0000' (null characters).

If the array data type is defined as boolean then each element is set "false".

Relative Addressing

The size of the array can be queried by using the Array Reference Variable Length.

ie.    int myTableSize = myArray.length

The array elements are accessed through an index.  The index variable must be an integer.

The first element of an array is Element ZERO.

ie.    myArray[0]

The last element of an array is one less than the Array Reference Variable Length,

ie.    myArray[myArray.length - 1]

Accessing an array out-of-bounds is a common programming error.  It will throw a runtime ArrayIndexOutOfBoundsException.  To avoid this error, make sure that you do not use an index beyond  arrayRefVar.length - 1.



Copying Arrays

To copy one array to another you can:
1) Use a loop to copy individual elements.
2) Use the static arraycopy method in the System class.

Note that the statement  arrayList1 = arrayList2 may appear to copy the array but it is simply creating another reference pointer to the same array.



Passing Arrays to Methods

JAVA uses "pass by value" to pass arguments to a method if the arguments are the variables of primitive data types.  For an argument that is of an array type, the value of the argument contains a reference to an array; this reference is passed to the method.

ie.    int[] x = new int[100];
        rc = someRoutine(x);

        public int someRoutine(int[] y)
        {...
        return 0;
        }

<

Returning an Array from a Method

A method may also return an array.  Again it returns a reference pointer to the caller.

.ie.    int[] x = new int[100];
        rc = someRoutine(x);

        public int[] someRoutine(int[] y)
        {
        int[] result = new int[10];
        for (int i = 0; i < 10; i++)
            {
            result[i] = i*2;
            }
       return result;
        } 




Week 10
Multi-Dimensional Arrays


Definition:

An Multi-Dimensional Array is a fixed-size sequential collection of elements of identical types, like a single dimensional array, but is is used to represent n-dimensional data structures.  During allocation the array size in all dimensions must be given to specify the number and type of elements that can be stored in it.

Arrays of 2 dimensions are called tables or matrices.  Tables are usually identified with rows and columns.



Prototype for Declaring a 2-dimensional array, a.k.a table:
datatype[] ArrayReferenceName;

Example:    String[][] myArray;



Prototype for Creating a 2-dimensional array, a.k.a table:
ArrayReferenceName = new datatype[number_of_row_elements][number_of_column_elements];

Example:    myArray = new String[100][50];



Prototype for Declaring and Creating a matrix in one step:
datatype[][] ArrayReferenceName = new datatype[Y number_of_elements][X number_of_elements];

Example:    String[][] myArray = new String[100][200];

This creates a tables of strings with 100 rows and 200 columns.



Relative Addressing
A multi-dimensional array is actually an array in which each element is another array. 

The elements  x[0], x[1], x[2], ..., x[n-1] are arrays in themselves. 

The size of the array in the first dimension can be queried by using the Array Reference Variable Length.

ie.    int myTableSize = myArray.length

The sizes of the arrays in the second dimension can be queried by using the Array Reference Variable Length of each element from the first dimension.

ie.    int myTableSize = myArray[0].length

        int myTableSize = myArray[1].length

        int myTableSize = myArray[myArray.length-1].length

The array elements are accessed through an multiple indices.  Each index variable must be an integer.

The first element of a table can be thought of as Row Zero, Column Zero .

ie.    myArray[0][0]



The last element of a table is one less than the Array Reference Variable Length for both rows and columns.

ie.    myArray[n][m]    

ie.    myArray[myArray.length - 1] [myArray[myArray.length-1].length - 1]


Week 11
Inheritance


Definition:

Inheritance is the object-oriented programming concept that allows you to derive new classes from existing ones.  In fact, every class in JAVA is inherited from an existing class, either explicitly or implicitly.  The parent of all JAVA classes is Object

If class PGM1 is derived from another class PGM2, then PGM1 is called a subclass (or child class) and PGM2 is called its superclass (or parent class).

A subclass inherits accessible variables and methods from its superclass.  

The subclass may extend the superclass by adding new variables and methods. 

Note that the subclass is NOT a subset of its superclass.  On the contrary since the subclass extends and is a specialization of the superclass; every instance of a subclass is an instance of its superclass. Therefore it is the superclass that is a subset of the subclass.  

The inheritance relationship enables a subclass to inherit features from its superclass with additional new features.

"this" and "super" keywords
The "this" keyword refers to the object or class in which you are in when using the keyword.
The "super" keyword refers to the superclass of the class in which you are in when using the keyword.

Calling Superclass Constructors
The syntax to call a superclass constructor is:     super();     or     super(parameters);

The statement super() must appear in the first line of the subclass constructor.  If not invoked explicitly then the compiler puts super() as the first statement in the constructor.

Calling Superclass Methods and Using Superclass Properties
The keyword super can also be used to reference a method or property that is accessible from the superclass.

            super.myVariable
            super.myMethod(parameters)

Overriding Methods
Sometimes it is necessary for the subclass to modify the implementation of a method defined in the superclass.  This is referred to as "method overriding"

Note: Static methods can be inherited but it cannot be overridden.

Polymorphism
Every instance of a subclass is an instance of its superclass.  Therefore, you can always pass an instance of a subclass to a prameter of its superclass type.  An object of a subclass can be used by any code designed to work with an object of its superclass.  This feature is known as polymorphism (Greek: meaning "many forms")

Polymorphism allows methods to be used generically for a wide range of object arguments.  If a methods parameter type is a superclass (ie. Object) you may pass an object to this method of any of the parameter's subclasses. 

Example:
public class PolymorphismDemo {
  public static void main(String[] args) {
    gprint(new GraduateStudent());
    gprint(new Student());
    gprint(new Person());
    gprint(new Object());
  }

  public static void gprint(Object x) {
    System.out.println(x.toString());
  }
}

class GraduateStudent extends Student {
    public GraduateStudent() {
        super();
    }
}

class Student extends Person {
    public Student() {
        super();
    }
  public String  toString() {
    return "Student";
    }
}

class Person extends Object {
  public Person() {
   }
  public String  toString() {
    return "Person";
  }
}

Protected Data and Methods
The modifiers private, protected and public are known as visibility or accessibility modifiers because they specify how class and class members are accessed.

A protected data field or method in a public class can be accessed by any class in the same package or its subclasses.

Use the private modifier to hide the members of the class completely so that they cannot be accessed directly from outside the class.

Use no modifiers to allow the members of the class to be accessed directly from any class within the same package but not from other packages.

Use the public modifier to enable the membrs of the class to be accessed by any class.

The private and protected modifiers can only be used for methods and variables.

The public and no modifier (default) can be used on members as well as the class itself.

 

Week 12
Abstract Classes and Interfaces


Definition:

Class design should ensure that a superclass contains common features of its subclasses.  Sometimes a superclass is so abstract that it cannot have any specific instances nor define any concrete implementation details defining behaviour.  Such a class is referred to as an Abstract class.  

Prototype:
public  abstract class myAbstractClass {
    public abstract int mySubroutine();
    public abstract int yourSubroutine();
}

JAVA does not allow multiple inheritance.  Each JAVA class may inherit directly from at most one superclass.  This restriction is known as single inheritance.

An abstract class will define methods that cannot be implemented in the superclass because their implementation details are dependent on the specific type of object being defined by the subclass. These methods are referred to as abstract methods.

Abstract classes are like regular classes with variables and methods, but you cannot create instances of abstract classes via the "new" operator.  An abstract method is a method signature without implementation.   The abstract class can contain concrete methods as well as signature-only methods. The implementation is to be provided by the subclasses.

An Interface is a classlike construct that contains only constants and abstract methods.  An interface is similar to an abstract class, but an abstract class can contain variables and concrete methods as well as constants and abstract methods.  Each method of an Interface has only a signature without implementation.

Prototype:
modifier  interface myInterfaceName {
}

Interfaces are similar to abstract classes and you can use them more or less the same way.

A class may implement multiple Interfaces.

An Interface may extend (and therefore inherit) multiple super Interfaces.

Both Abstract classes and Interfaces are used to define generic classes and methods.



[Return to Professor Page]