Robotics Programming Lecture Notes

Fundamentals


Topic 1
Introduction and Fundamentals




An algorithm is a procedure for solving a computing problem in a finite number of unambiguous steps that frequently involves repetition of an operation, but will eventually accomplish the problem task, produce a result, and halt.

All operations used in the construction of algorithms belong to one of only three categories:

Sequential – imperative statements that follow one another.

Conditional – execute some set of statements on the basis of a condition.

Iterative or Recursive – execute the same set of statements some definate number if times or while some condition holds true.

Good algorithms are not only correct, but must be efficient to be useful.



Algorithms provide us a procedural way to take a manual function and then automate it.

Any operation that can be accurately described with a procedure can be mechanized, thereby freeing the operator from that work.





What is Computer Science?

Computer Science is the study of algorithms.









Computer Science and Programming Terms

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. The implementation of an algorithm. Also known as software, programming will provide the computer with a step-by-step procedure in some programming language, to solve some problem.







Languages

Microcode or Firmware -- Programming code that instructs the hardware on how to carry out a very low level task, such as openning a circuit gate, ORing and ANDing differences in voltages that represent signals.

Machine -- Code that is understandable by the hardware. Strings of ones and zeroes. Machine code is printed in hexadecimal for humans to have a chance at reading.

Assembly -- (such as IBM Basic Assembly and Intel 8066 Assembly). 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 -- (such as C++, COBOL, Fortran). Source code gets translated by a compiler into Assembly language, then the machine code of the architecture.

Interpreted -- (such as JAVA, REXX, EXEC). Interpreted languages translate or are initially written in architecture neutral code, that the installed intrepreter on each of the different architectures then translates “on-the-fly” at execution time the code into the machine language of the environment.

Command Language -- (such as BASH, JCL, BAT) These are interpreted languages generally used for operator communication with the operating system.

Pseudocode notation is a set of English language-like constructs designed to be easily converted by humans into formal statements of a programming language, but in itself does not actually execute on a computer, nor can be used for translating to machine executable code.



A program written in a given language form is called the source program.

(a) If the source program is translated by a compiler to produce an object program. This 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.



(b) If the source program, may or may not require a compilation process, but is translated at run time by an interpreter into executable machine language, then it is called an interpreted language.



Compiled languages are more resource efficient than Interpreted languages. Resources consumed include CPU cycles, memory and movement of data in and out of memory.



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 to supplied language classes and subroutines along with 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 Oracle NetBeans, it is used to create, edit, organize, compile, debug and execute programs from scratch.





Language Elements and Statement Structures in 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.

Literals are strings that evaluate literally. Literals are enclosed in double quotes.

Comments are used to help programmers communicate information regarding the logic and to help remember what the code actually does. // is used for a single line, /* ...stmts... */ is used for a block of lines.

Classes or programs 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 or subroutines are a procedural set of instructions or statements, a routine, that may take arguments and performs some work and may produce a returned result. Methods define the behavior of a program.

Properties or variables are definitions of data which include its type, value and number of storage bytes allocated. All property names (identifiers) are case-sensitive. Variables hold the state and state changes of a program.

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. Every class that is to be invoked by the JVM must include a main method. The main method must be defined as static . Classes called by other classes do not require a 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.



Instance vs. Static variables or methods
If a variable or method is defined as static, then there is a single copy available and shared by all who used it. You can access it by its name.

If a variable or method is defined as an instance, then there is a multiple unique copies. You must use an identifying reference variable along with the variable or method name to access the proper copy.





Method Header

Visibility    Scope    Return_Type    MethodName   ( Argument_List )

Examples:

public static void main( String[] args )

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



The method header tells you everything you need to know to easily construct calls and returns to the method itself:

First, it tells you the name of the method.
Next, it tells you about the input that it MUST receive: the number and types of arguments.
Lastly, it defines the existence and type of result that MUST be returned by the method.









Topic 2
Primitive Data Types
and
Language Definition Fundamentals


Bits and Bytes

A BIT is the fundamental information element in a computing system. It represents the smallest unit of information. A true or false, on or off, 1 or 0.


A BYTE is a contiguous string of eight bits. The byte is the smallest addressable unit of memory in a computing system. Amounts of memory are counted in bytes.

Bits are NOT addressable. To manipulate a bit you must address the byte in which the bit resides and use special instructions to change the bit's value.





Data Types in JAVA

JAVA is a strongly typed language, This means that every defined variable must have a declared type, otherwise the compiler/interpreter will raise an error.

A primitive type is a datatype that is pre-defined by the programming language and named by its reserved keyword.

There are eight primitive variable types (int, short, long, float, double, boolean, char, byte). The primitives are provided by the language. Each primitive has a size of allocated memory, a permissable use and a provided set of manipulations that you can perform using them. All other data types are defined by the programmer.

The datatype of any variable is determined by the class (program) that defines its properties and behaviors.

Example:

The properties and behaviors of the primitive datatype int is defined by the internal class int that was provided by the JAVA language.

int    x = 123;
int    y = 432;

The properties and behaviors of a reference variable, say P, is determined by the methods that are programmed into the class named myProg.
Below is an example of creating a two new instances of some class myProg. Both P and Q are said to be of datatype myProg.

myProg    P = new    myProg();
myProg    Q = new    myProg();









Variables or Properties

The JAVA programming language uses both "fields" and "variables" as part of its terminology.

Note: JAVA is CaSe-SeNsitivE

A variable is a symbolic name (or handle) that represents some data in storage and holds some value.

Example:
int X = 123;

The variable known as X, at some location in memory, contains the integer value of 123.



Instance variables (non-static fields) are unique to each instance of a class.

Static variables (static fields) are fields declared with the static modifier; there is exactly one copy of a class variable, regardless of how many times the class has been instantiated.





[ Visibility ]    [ Modifier ]    DataType    VariableName  [ = Initial Value ]


Examples:

public static    int    x = 123;
private double    y = 7.5341;
boolean    status = true;
int    z = 0;



If visibility or modifier are not specified then the default is public and non-static.





Literals are strings that evaluate literally. The value of a Literal is literally itself. Literals are enclosed in double quotes.


"The End" is a literal.

System.out.println(   “Hello World”   );





Bytes are single characters. An entry of the ASCII table. They are enclosed in single quotes.

'A' is a character.

char ch = 'A';





Variable Types

<Integer Types> <Storage Used> <Range of Value>

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 data type. Referencing a defined variable after its definition does not require using the type.

Examples:
int    mynumber = 10;
int    x;
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.123;
double    myDoublePrecisionNum = 456.1234567892;





Character Type
In JAVA the char type represents a single character.

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



The first \ serves as an "escape character".







boolean Type
The boolean data type represents a logical indicator that 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    semaphore1 = true;







The ASCII Code

ASCII stands for American Standard Code for Information Interchange. Computers can only understand numbers, so an ASCII code is the numerical representation of a particular character.

The ASCII codes represent the text letters, numerals and special characters found on the computer keyboards. Further, there are codes that represent special situations for controlling how the text is processed.

There is a one-to-one relationship between each text character and an ASCII table entry.

ASCII is the alphabet of computer languages.

The codes range from 0 to 127 in decimal (0 to 7F in hex) numbers.





CODE versus DATA

Code is executable. Code represents instructions to be executed.

Data is non-executable. Data represents information.





CALLs and RETURNs

When we wish to transfer control to another method we use a method or function call. A call branches to the routine we specify.

We use a return statement to terminate a method and specify what result (if any) it should return Whenever a method executes return, no matter what else it is is doing (i.e., inside loops or try-catch ,etc...), the method immediately terminates and returns to where the method was called (its call site). Actually it returns to the next statement following the call site.

If the method returns a value, it is as if the method call is "replaced" by the value that it returns as a result.

Ideally, a method should contain just one return statement, at its end. In fact, we can prove mathematically that there is always a way to write a method with one return statement. But sometimes methods are easier to understand if they have multiple return statements.

Optionally, we can supply arguments or parameters to the called method to be uses as input.

double someNumber = 1234;
myResult = findLogarithm ( someNumber );
System.out.println( “The log of “ + someNumber + “ is “ +       myResult);



Optionally, the called method can return to the CALLING method a result.

double findLogarithm ( double N)
{
      :
      :
      return X;
}





Command Line Arguments

At times it is desirable to pass a program data in the form of arguments.

Take for example the Windows command COPY.

COPY C:\myfolder\mydata C:\targetfolder\



This example shows us that the COPY program invocation specifies a source data file and a target file.

The program COPY must capture these arguments at the beginning of its execution.

Arguments are passed to the JAVA main method.

void main ( String[] args)



Topic 3
Standard Input/Output
and
Arithmetics


Standard Input


This is input data that is read from characters entered on the keyboard.


The Scanner Class is normally used to perform this function. Since Scanner is an instance class you first have to instantiate a copy of it. After defining a reference variable to the class you then use this to perform the read operation.

Example:


Scanner myscan = new    Scanner (System.in);
String myinput = myscan.nextLine ( );




Standard Output


This is output data that is directed or written to the console.

The System Class is normally used to perform this function. Since System is a static class you will NOT need to instantiate a copy of it, but simply use it by its name along with its qualified methods to perform a write operation. The actual output is supplied as arguments.

Example:


System.out.println ( "This is my output " + mydata );




Standard Error


Similar to Standard Output, this is error data that is directed or written to the console, usually in the color red.






Program Instantiation


Instantiation is the process of:

searching by the operating system for the new program,
measuring its size
in bytes,
allocating sufficient
contiguous memory,
fetching of the program from its storage area and placing it into memory,
providing addressability by way of a
reference variable.

Immediately following, transfer control to the constructor method of the new instance, and finally giving control back to the calling program at the next instruction.



Main Method requirements

The JAVA Virtual Machine (JVM) starts execution by invoking the method main of some specified class and passing it a single argument, which is an array of strings. This causes the specified class to be loaded, linked to other types that it uses, and initialized. The method main must be declared by design as public, static, and void return.

By design, the JVM can only call (start off) the main method of a class without the requirement of instantiating an object of the class. By design this necessitates the method to be static.

To get around the restriction of having to operate in a static environment it is important to have the main method immediately instantiate a copy of the program in which it resides, and then to transfer control to some non-static method in that instance. This relieves us of operating with the restrictions of a static world allowing us to access both instance and static type methods and variables.



Example: These are the only requirements for the main method; instantiate this program, transfer control to the new instantiated object by calling the first method, and later return control back to the JVM.

public static void main ( String[] args )
{
        labx p = new labx();          //Instantiation commences
        int src = p.process();         //Call a method of new instance
        System.out.println( "process return code is " + src );
        return;                //Transfer control back to the JVM
}





Arithmetic Operators

Addition    +

Example:
int c = a    +    b;


Subtraction    -

Example:
int c = a    -   b;


Multiplication     *

Example:
int c = a    *    b;


Division     / 

Example:
int c = a / b;


Modulus (remainder)    %

Example:
int c = a    %    b;




Increment/Decrement ++ and -- (used before or following the variable)

When used before the variable the value is changed by 1, then the entire statement is evaluated.
When used following the variable the entire statement is evaluated, then the value is changed by 1.



Assignment Operator

=     (EQUALS, that is the left side of the equation takes on the value of the right side.)



Relational Operators

==     (EQUALS?, this is the test of equivalence between the value of the left and right sides.)

!=     (NOT EQUALS)
<
>
<=
>=



Logical Connection Operators

&&    (AND)
||    (OR)


Negation    !    (NOT)


Do not confuse the "=" sign which means assignment with the "==" sign which means test for equivalence.





Simple Math Functions using the Math Class and some of its supplied methods:


y = Math.sqrt( x );   square root of x
y = Math.pow( x, a );   x raised to the power of a
y = Math.sin( x );
y = Math.cos( x );
y = Math.tan( x );
y = Math.exp( x );
y = Math.log( x );
y = Math.PI;   the value of PI ( 3.14159 )
y = Math.E;    the value of e ( 2.718281828 )





Named Constants

Constants are defined like variables with an initialized value, but with the modifier final. The constant may not take on another value in the source code.

Example: public final double PI = 3.14159;





Strings

Strings are sequences of Unicode characters. The String is not a JAVA primitive but a predefined JAVA datatype managed by the "methods and properties" of a programmed JAVA class. Each string is an instance of the String class.

Strings can be instantiated either by using the formal method:

String s = new String(“Hello World”);

or via a shortcut permitted by the JAVA implementation:

String s = “Hello World”;



We will discuss more about Strings and Classes in the next semester.

Unreferenced strings (those not in use) are automatically "garbage collected" by the JAVA Virtual Machine.

The reference variable of the String points to the contents of the String as well as the various methods to manipulate the String.

Passing the reference variable as an argument of System.out.println() will cause the contents of the String to be displayed on your monitor.

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

System.out.println( msg);    //This will print the message literal on your console



Here as some useful String conversions for this semester:



Converting 1 character of a String to Character datatype


To convert a single character contained in a String to a Char datatype use the charAt(n) method of the String class.


To select the first character of a given String

String s = new String(“This is a test”);
char ch = s.charAt(0);
System.out.println(“The first character is “ + ch); //prints T





Converting a character to a String of length 1


To convert a single primitive character to a String use the valueOf() static method of the String class.


To select the first character of a given String

char ch = 'M';
String s = String.valueOf( ch );
System.out.println(“The String is “ + s); //prints M





Selecting a single character of a String as a subString
To select a single string character of a String use the substring(n,m) method of the String class.


To substring a single first character of a given String

String s = “Hello World”;
String h = s.substring(0,1);
System.out.println(“The String is “ + h); //prints H





Finding the number of characters in a String, its length


To find the length of a String use the length() method of the String class.


To obtain the length of a given String

String s = new String(“This is a test”);
int l = s.length();
System.out.println(“The length of the String is “ + l); //prints 14





Converting Strings to Integers


To convert a numeric string into an int value use the parseInt method of the Integer class.


int myint = Integer.parseInt( mystring );





Converting Strings to Long Integers


To convert a numeric string into an int value use the parseLong method of the Long class.


long x = Long.parseLong( mystring );





Converting Strings to Floating Point Numbers


To convert a numeric string into an int value use the parseFloat and parseDouble method of the Float and Double classes, respectively.


float y = Float.parseFloat( mystring );
double y = Double.parseDouble( mystring );









Where does JAVA flag errors

Errors that are caused by syntax or semantics (language use) are caught at compile time in the source code. Source code uses a file extension of .java

Errors that are caused by logic flaws may be caught at runtime (execution). JAVA executable code uses a file extension of .class

Note a clean compile is no indication or guarantee that your program will run successfully.





Use System.exit() with care

From Oracles's Portability Cookbook:

"The System.exit method forces termination of all threads in the Java virtual machine. This is drastic....System.exit should be reserved for a catastrophic error exit, or for cases when a program is intended for use as a utility in a command script that may depend on the program's exit code."

The correct way to normally end a program is for the main thread to transfer control via the main method's return statement to the JVM.



Topic 4
Conditional Decision Logic and Flow Control




Flow Control

Program flow control concerns itself with the order in which statements are executed in a program. Most programming does not execute its statements in strict linear 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 has evaluated as true and alternative actions when the condition has evaluated as false.

Each alternative causes a bypass of the code making up the path not chosen.



Prototype:

            if (condition_is_true)
           {
               statements for when condition is true;
           }
           else
           {
               statements for when condition is not true;
           } 



Example:

                    boolean starsAreOut = true;


                    if (starsAreOut)
                    {
                        System.out.println("It is night.");
                    }
                    else
                    {
                        System.out.println("It is daytime.");
                    }



Note: during evaluation of the IF statement using a boolean, that if the test for equivalency operator is not present than it is assumed that the operator is "==".

Also note that the "if" and the "else" do not have semicolons following the conditional.





Nested If

Nested IF statements are used to simplify code reading for the programmer when you find it necessary to evaluate a first condition, then, if true evaluate a second condition in order to make a decision to perform some set of instructions. You may find the need to use nested IFs if it becomes necessary to perform more than two tests tests for truth and you have a number of instructional paths to take depending on the truth or falsity of a set of conditions.

When using IF-ELSE pairs you should attempt to match each ELSE with a preceding IF statement.

For readability, keep each IF-ELSE block of code enclosed in braces and indented appropriately in your source code.

The inner statements are said to be "nested".

There is no limit to the depth of nesting, but after a few it does make it quite difficult to match up your IF and ELSE statements.



Example:

boolean starsAreOut = true;
boolean moonIsOut = false;


if (starsAreOut == true)
{
      System.out.println("It is night.");
      if (moonIsOut == true)
      {
            System.out.println("And, the moon is out.");

            /* more statements */
      }

       else
      {
            System.out.println("And, the moon is NOT out.");

            /* more statements */
      }
}
else
{
      System.out.println("It is daytime.");
}





Example: Logic to determine what to do if the moon is out on a cold night

boolean starsAreOut = true;
boolean moonIsOut = false;
boolean itsColdOut = true;


if (starsAreOut == true)
{
      System.out.println("It is night.");
      if (moonIsOut == true)
      {
            System.out.println("And, the moon is out.");

            if (itsColdOut == false)

            {

                  System.out.println(" And, its NOT cold.");

            }

            else

            {

                  System.out.println(" And, its cold.");

                  /* more statements */

             }

      }

      else

      {

            System.out.println(" The moon is NOT out.");
      }
}
else
{
      System.out.println("It is daytime.");
}






Compound Conditionals

A compound conditional is where multiple related conditions are evaluated in determining if the entirety is true. The conditions are connected by AND and OR conjunctions.


While there is no limit to the degree of compounding, but it becomes more difficult for humans to evaluate as the number of conditions and their relations increase.



Example:

if ( ( a > b) && ( b < c) )


if ( a || b)


if ( a && !b)







Lecture FYI


At this point in the course you should be now comfortable with the JAVA syntax and knowledgeable with using the JAVA API to look up any JAVA class and its methods.

The text is your reference, as are the reliable sources found over the Internet


Therefore, your instructor will no longer be aiding you with these matters of the JAVA language.


From this point forward we will focus on Computer Science which is the study of algorithms. This means that most of our time will be concentrated on solving the problem at hand with flowcharts and pseudo-code.




Topic 5
More Flow Control
And Branching


The SWITCH statement

SWITCH construct statements are employed when nested or multiple IF-ELSE statements would make a program more difficult to read and be interpreted by the human programmer.

The SWITCH statement will handle multiple conditions efficiently and may make the code easier to program and debug.



Prototype:
                switch (expression to be evaluated for a value)
                {
                    case value1:
                    {
                              statements;
                              break;
                    }
                    case value2:
                    {
                              statements;
                              break;
                    }
                    case value3:
                    {
                              statements;
                              break;
                    }
:
:
:
                    case value N:
                    {
                              statements;
                              break;
                    }
                    default:
                    {
                              statements;
                    }
               } //End of Switch
               <next statement>



The "switch" statement will check all cases and execute beginning at the statement where the case matched the switch value.

It will execute or "fall-through" of all remaining statements unless there occurs a "break" statement.

The “break” statement will force a branch or jump, that is the flow of execution to exit the switch construct. Program flow will continue with the statement immediately following the end of the "switch" statement.



The switch "expression" must yield a value of byte or int datatype.

The "value" of case must have the same data type as that yielded by the switch "expression".



Each case labeled statement then compares or tests the switch result with its case-value.

If the two match then that branch of logic statements is taken.

If the two do not match then the immediately following case statement is evaluated in the same manner.

This continues until either there is a match or until all the case statements are exhausted. In which case the last statement of the switch-case set, the default, is taken.



Note that after a particular case matches and its statements are executed, program flow will continue with the next case statement unless you use a break statement.

Note that the case statement ends with a colon (:).





Further Syntax Reminders

All statements end with a semi-colon with the following exceptions:

class headers
method headers
if
else
for
while
switch

Each of the above exceptions begin a block of code and therefore end with an OPEN BRACE { and finish with a CLOSE BRACE }.

By convention all class names begin with an capital letter.

All method names begin with a lower case letter but use a capital letter for subsequent parts of the name.
Such as: nextInt(), toString().





Branching

The term branching refers to a change in the normal linear flow of instruction or statement processing. When a branch is taken the processing is requested to go to another instruction somewhere else in the program other than the immediate next instruction.

JAVA statements that cause a branch:

break;

This statement causes a jump to the end of an if, while or switch

return;

Causes a jump to the next instruction following the call to the current method.

method_call();

Cause a jump to the named method. Saves the current location for later processing by the return statement of the named method.







To access the SWITCH-CASE example: caseswitch.java







Topic 6
Problem Determination and Good Habits


What is meant by debugging?
A bug is a logic error or flaw in the programming that leads to incorrect or unpredictable results.





Program Problem Determination includes but is not limited to:

"eyeballing and staring" at your code,

requesting help from a colleague,

floating your cursor over the error in the IDE,

looking up the error message in the API,

instruction stepping and tracing,

trying out your programming as you progress,

placing displays of literals or variable contents at particular points in the program,

keeping the program human readable using comments and choosing sensible method and variable names,

Google It,

sleeping on it,

dumping memory (ugly),



We will focus on keeping the program human readable, displaying variables at code points, and using our IDE to trace the execution of our code.





Attacks for Lightweight Programmers

Guessing.

Compiling and running in your head.

Treat the program as though it has human qualities.

Asking someone else about what is wrong with your program.

Ignoring or dismissing the problems as "FLUKES" and hoping that they go away by themselves.

Blaming the IDE, compiler, machine or some other mechanism.





Leverage the knowledge you have acquired from your prior programs.





Be aware that the way you perceive the program to be executing may be completely different from what is actually happening in the computer hardware.

Don't make the mistake to attempt to compile the code in your head.

Don't waste time trying to understand why code appeared to function correctly when found later to be faulty.

It is easy to explain why proper code and logic functions correctly.

It is very difficult to explain why improper code and logic seems to function much of the time.







Readability

Every block of code, that is, code bounded by a set of braces {} should be indented by 4 spaces. The open and close brace should appear in the same column.



All reserved constructs whose next line is an open brace { will not end in a semicolon. Such as “if, while, for, switch, etc.”





Using the IDE

Reserved words are highlighted in the same color.

If during an execution you get a STACK TRACE then you have a pointer to the line of your program that is generating or causing the error. The flow of code leading to the error starts at the bottom of the STACK TRACE and works upwards. Your error will be the line number of the uppermost trace entry that identifies a program or class that you wrote.







Statement Tracing with the IDE

A trace is the ordered list of instruction locations visited during program execution.

At each trace point, you will have an instruction that is to be executed. The variables involved as operands can be viewed as to their current values. Following a step through operation by the tracer you can see the results of the execution and the change in variable values.



The IDE allows us to set trace points, instruction step through each line of our source code, jump over tracing of uninteresting routines and resuming normal execution.





Most sure fired way to reduce logic errors

FlowChart

A flowchart is a schematic that depicts the logic flow of an algorithm. Flowcharting IS programming.

Each part of the algorithm is diagrammed in separate boxes representing the processing at that point. The boxes are joined by arrows representing the direction of flow.

Generally the process boxes have one or more entry arrows from some other process, and one or two exit arrows that lead to the next step in the processing.

A flowchart is used to design, analyze, modify and most importantly document the programmed processes and their interrelationships of an algorithm.

Using a flowchart significantly decreases the number of logic errors in new programs; and reduces the time needed to understand and modify existing programs.

If the algorithm cannot be flowcharted then it cannot be programmed.



Pseudo-code

Once you have a solid flowchart, then write out your major steps followed by the detail of your minors steps in pseudo-code.



Re-use code

Save your successful routines to be used again with future programs. Collect a tool kit of reusable routines.







IMPORT statements allow us to include source code referenced by our program but written elsewhere usually by some other programmer.

Example: import java.util.*;









Note about returns from method calls

It is accepted and standard good practice to always return some completion status from each method call that indicates the success or failure of the method function. Such as a boolean for success or failure. Or an integer where zero indicates successful completion, and a negative value that indicates both a failure and its severity.

Without such return codes you have no basis of programmatically determining the next procedural step for your algorithm. Your programming requires an affirmative acknowledgement from each called routine before it can safely continue or determine some remedial action.









Topic 7
Repetition


LOOP Statements



Loops are constructs that control repeated iterated executions of a block of statement code.

Each loop contains a loop continuation condition that mediates the execution. The test for termination is performed at the top of the loop construct.

Prior to each iteration the loop continuation condition is re-evaluated to determine if further iteration is warranted..

If the evaluated condition remains true, then the execution continues.

If the condition is evaluated as false then the loop terminates immediately and passes control to the next statement outside and following of the current loop.



There are four types of loops provided by the JAVA language: while, for, do-while and for each. We will study the first three.





Definite Iteration:

the for loop

for (initial_value; while_condition_is_true; action_after_each_iteration)
{
       statements;
}





Indefinite Iteration:

the while loop

while (condition_is_true)
{
       statements;
}





the do while loop

do
{
       statements;
} while (condition_is_true)



(The do-while loop is pretty much the same as the while loop with the exception that the statements get executed at least once prior to the initial evaluation to continue.)



The occurrence of a “break” statement will cause an immediate exit of the loop in which the break occurs, and only the loop in which it occurs.

Any loop can be terminated early by way of the break statement.





Any single iteration within a loop can be terminated early by way of the continue statement. The continue statement will cause a preempting of any further statements in this iteration of the loop and commence execution with the start of the next iteration of the loop.





Nested loops are secondary loop constructs found within loop constructs. The nested inner loop appear to the outer loop as an embedded statement to be executed independently.

Example:

for (initial_value_a; while_condition_is_true;        action_after_each_iteration)
{
      statements;


    for (initial_value_b; while_condition_is_true;           action_after_each_iteration)
    {
           statements;
           statements;
     } // end inner loop


     statements;
} // end outer loop



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.



How would you break out of all nests of loops from an inner loop?







Recursive Looping

An algorithm or method is RECURSIVE if it defines a procedure in terms of a simpler case of itself.


A recursive program is one that is required to invoke itself. Every invocation of itself leads to a simpler problem. The same computation recurs, or occurs repeatedly, until the problem is solved.



A recursive call can result in many further recursive calls because the each call is dividing the problem in new smaller subproblems, or smaller instances of the same problem.



For a recursive method to terminate, the problem must eventually be reduced to a stopping case. The stopping case is a trivial result to the current level of the recursive procedure that requires virtually no computation to produce an answer.



There must be a "way out" of the sequence of recursive calls.  When reached, the method returns a result to its immediate caller. This caller, in turn, performs a computation and returns a result to its own caller. This process continues unwinding the sequence of recursive calls until a result is percolated back up the calling chain to the original caller.



Infinite recursion happens either because the parameter values passed during a recursive call do not get simpler or because a special terminating "stopper" case is missing or never reached.





Recursion vs. Iteration

The difference between a recursive function and an iterative function is that the iterative type calls for the explicit repetition of some process until a certain condition has been met.



From a programming point of view, the recursive solution may be the most natural and logical way of solving a problem.





To access the LOOP example: loops.java

To access the JAVA source code: recursetest Factorial Sumtorial







Topic 8
Calling Functions and Transfer of Control
and
Garbage Collection


Calling a Method

In creating a subroutine, you define the details of the work that a routine must perform. To employ the subroutine you have to call or invoke it by way of a method call.

The subroutine must reside in either the class from which it is called or another class to which your program has access.

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:

double 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");





Please note that if a method returns no value then there is no easy way to determine the success or failure of the work that the method was to carry out.





Method Prototype Definition:

modifier         return_value         method_name ( arguments )

public int mySubroutine ( int arg1, int arg2, String arg3 )



A method that takes no arguments is called a No-Arg Method.





Prototype for Invoking a method:

datatype result = method_name ( arguments );

int rc = mySubroutine (arg1, arg2, arg3, arg4,...,argN);





Transfer of Control

When one method calls another method, program control is transferred from the calling method to the called method.

The called method header saves the address of the instruction that initiated the call. This address is made available to the subsequent return statement so that we can find our way back to the caller.

The called method returns control to the caller when its return statement is executed. The return uses the address saved by the method header.





Passed Arguments

Each argument, if any, in the calling statement is matched positionally with arguments in the called method.

The datatype, number of args and the order in which they appear. This is known as the signature of the method.

All primitive arguments are passed by value. Changes made to the variable(s) in the called method do not affect the variable(s) in the calling method.

An argument passed by value denote that two allocations of storage with different memory locations will contain the same value.





Returned Result

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

The return type on the method header must match the type on the return statement.

The return statement variable and the receiver variable will contain the same value upon transfer of control.





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". This means that its name and value is accessible to all methods in the class.





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 code that 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 by programmers, their application programming interface (API) must be well documented.





Note about returns from method calls


It is accepted and standard good practice to always return some completion status from each procedure call that indicates the success or failure of the procedure. Such as a boolean for success or failure. Or an integer where zero indicates successful completion, and a negative value that indicates both a failure and its severity.


Without such return codes you have no basis of programmatically determining the next procedural step for your algorithm.

Proper programming requires an affirmative acknowledgement from each called routine before it can safely continue or determine some remedial action.






Why dedicate a separate Procedure for each unit of work?


You could program all the different units of work required to complete a task in a single procedure, but the program would be more difficult to maintain, modify and decompose for routines that may be useful in other programs.


It is best and good practice to use separate procedures for each unit of work in a task.



Advantages:


A complex task may be for easily divided into smaller simpler tasks.


A program becomes easier to maintain because each smaller task is encapsulated in its own procedure.


The "top down" approach to design lets you see how the procedures are related to one another before writing any code.


When you gain confidence in the overall design, you can more easily manage the details and logic of the code that implements each procedure.


Flaws due to logic will generally be isolated to a single procedure.


Common procedures can be placed in a library, documented and shared by other programs.


New programs can quickly be assembled by selecting procedures "off-the-shelf" , then threading them with logic to make a unique new program.


As you gain experience your main programs become a series of procedure calls and checking of results.







Garbage Collection


Garbage Collection is the term we give to the recovery of storage that is no longer being used by code and variables JVM will gather all items that it has determined as no longer needed by an executing program(s). The JVM performs this work on a regular basis when it finds the time and need.


You can force garbage collection by using the System.gc() method.


Data that you wish to be garbage collected can be marked as candidates by setting their reference to NULL;


Let P refer to an instance of some class X;


P = null;


will cause the object or the instance of the class pointed to by P to be setup to be garbage collected.





System Exit vs. Program Exit


The “return” of the main method transfers control back to the JVM with then terminates the program and runs garbage collection on the carcass.


System.exit()caused the immediate termination of the issuing program and all other programs running under the JVM, then terminates the JVM itself.









Topic 9
Arrays


An Array is a fixed-size, sequential collection of elements that are of identical data types.

During allocation the array size must be given to specify the number of elements that can be stored in it.

Arrays are "immutable", that is you cannot change the size of an array after it has been defined.

Arrays provide a convenient structure to traverse (or access) when you have a large number of data items that need to be manipulated in similar ways.

Any operation that you can perform over a single variable you can also perform on an single element of the Array.

You can think of an array as a LIST of items.



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 a single step:
datatype [] ArrayReferenceName = new datatype [ number_of_elements ];

Example:

String[] myArray = new String[100];





Prototype for Declaring and Creating an array by enumeration (not recommended):
datatype [] ArrayReferenceName = {elements listed and delimited by commas };

Example:

int[] numArray = {1, 3, 5, 7, 11, 13, 17, 19, 23, 37};

The compiler will count the entries for you and load each entry with the next value.



NOTE: While the array variable appears to hold an array, it actually contains just a reference to that array. That is, the array reference variable (that is known to you by the name of the array) is a pointer to the address of the virtual storage that contains the first element in the array. The array reference variable (the name) and the array (the area of virtual storage) are in different locations.







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 (such as int or float).

If the array data type is defined as char then it is filled with a NULL (unicode character '\u0000').

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



If the array data type is defined as String then recall that a String is an array of characters. So a String array is an array of arrays.



The String array reference variable points to an array of addresses. Each address is either 32 or 64-bits long depending on the computer architecture. Each address in turn points to a character array. Since we do not know the size of the strings to populate the array the character array entries are initially filled with a NULL (ASCII character x'00').

Do not rely on initial storage contents. Always initialize your arrays.







Array Size Query

The size of the array can be queried by using the Array Reference Variable Length. This is a built-in property to determine the array size.

Example:

int myTableSize = myArray.length



Note that the '.length' is a field or property of the Array class, not a method. There are no parentheses.





Relative Addressing

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

The first element of an array is Element ZERO.

Example:    myArray [ 0 ]

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

Example:    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 the array reference variable of "length - 1", nor an index that is negative.





Copying Arrays

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

Note that the statement bigArray1 = bigArray2 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. Actually this is a pointer to the zeroth element of the Array.

This reference or pointer is passed to the method, NOT THE VALUE OF THE ARRAY.
This is called "pass by reference".

The variable referred to in the subroutine is the SAME STORAGE ADDRESS as the variable in the caller, EVEN THOUGH THEY MAY HAVE DIFFERENT NAMES.

It is much less resource intensive to pass the address of something than a copy of the something itself.



Example:

int[] x = new int [ 100 ];
rc = someRoutine( x );
:
:
public int someRoutine( int[] y )
{
      ...
      return 0;
}

Changes made to the array in the called routine do, in fact, change the value of the array in the calling routine.





Returning an Array from a Method

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



Example:

int [] x = new int[ 100 ];
myAnswer = someRoutine( x );
:
:

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



Recall that a String is an array of characters. So passing a String as an argument to a method is the same as passing an Array. The method receives a reference pointer, NOT a copy of the String value.



Please note that since Arrays are passed by reference, there is no need to use the “return” statement to pass back an array. Many programmers find it more natural to use one of the method arguments as the output result. This gives you the extra capability of reserving the “return” for information regarding the success or failure of the method.





To access an Array example: arrayexample.java











Topic 10
Multi-Dimensional Arrays


Like a single-dimensional array a Multi-Dimensional Array is a fixed-size sequential collection of elements of identical types.

During allocation the array size must be given to specify the number of elements that can be stored in it.



Conceptual Examples:

You can think of a two-dimensional array as a TABLE with rows and columns.

You can think of a three-dimensional array as a CUBE with length, width and depth dimensions.

You can think of a four-dimension array as the coordinates to a meeting in New York City. This would include avenue, cross-street, floor and time of day.





Prototype for Declaring an array:
datatype [][]...[] ArrayReferenceName;

Example:

String [][] myArray;
int [][][][] myCoords;



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

Example:

myArray = new String [ 100 ] [ 50 ];



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

Example:

int [][] myTable = new int [ 100 ] [ 70 ];



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 (int or float).

If the array data type is defined as char then it is filled with a NULL (ASCII character x'00').

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

If the array data type is defined as String then recall that a String is an array of characters, thus making the String Array an array of addresses, where each address points to a string of characters in virtual storage.

Do not rely on initial storage contents. Always initialize your arrays.







Array Size Query

Like the Single-Dimensional Array the size of the array can be queried by using the Array Reference Variable Length. However in a Multi-Dimensional Array there are multiple length fields. Each length field for an given row holds the number of columns in that row. Each length field for a given column holds the number of rows in that column.

Example:

int myColumnSize = myArray[ somerow ].length

int myRowSize = myArray.length





Relative Addressing

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

The first element of an array is Element [ ZERO, ZERO ].

Example:    myArray [ 0 ] [ 0 ]

The last element of an array is

Example:    myArray [ N - 1 ] [ M - 1 ]



Accessing an array out-of-bounds is a common programming error. It will throw a runtime error known as an ArrayIndexOutOfBoundsException.

To avoid this error, make sure that you do not use an index beyond its defined length in any dimension, and do not use an index that is negative.





Copying Arrays

Like single-dimensional 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 bigArray1 = bigArray2 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 or pointer is passed to the method, NOT THE VALUE OF THE ARRAY. This is called "pass by reference".

It is much less resource intensive to pass the address of something than a copy of the something itself.

Example:

int[][] x = new int [ 100 ] [ 200 ];
rc = someRoutine(x);
:
:
public int someRoutine ( int[][] a )
{
      ...
      return 0;
}





Returning an Array from a Method

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

Example:

int[][] x = new int[100][40];
int[][] y = someRoutine(x);

:
:


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


To access an example: threedarray.java







Topic 11
Inheritance


Theory

Object Oriented programming permits other classes to have a parent-child relationship. This allows classes to inherit the state and the behavior of another class; that is defined constants, variables and methods)

The inheriting class or derived class is said to extend the functionality of the base class.

The base class is the more general class and the derived class can perform all that the base class can but it becomes a more specialized, more specific functioning class.

The derived class inherits the member variables and member functions of the base class without any of them being required to be rewritten or copied into the derived class.

Further, different member variables and functions are added to the derived class to make it more specialized and thereby increase the functionality that was available in the original base class.





Class Relations
The base class being extended is also called the superclass or parent class.

The derived class extension to the superclass is also known as the subclass or child class.





Scope of variables and methods
The derived class can access the non-private members of the base class. Variables and methods that are allowed to be inherited must be defined in the base class as either PROTECTED or PUBLIC.

Methods in a derived child class have access to all protected members (as well as public) in the parent super class.

Methods in a program that call on the services of the child class will not have access to the class' protected or inherited members.



Defined PRIVATE members in a parent class are hidden from child subclasses.



The derived class may call on any inherited variables or methods as though they had been defined locally in its own class.





Method Overriding
Methods in the derived class that have the same name and signature as the parent class methods are said to be overridden by methods in the child class. Note, when the signatures are different then no override takes place.



Advantages

Code Reuse
One of the key benefits of inheritance is to minimize the amount of duplicate code in an application by leveraging recognized common methods and variable code among several subclasses. Where equivalent code exists in two related classes, the hierarchy can usually be re-programmed to move the common code back to a mutual superclass from which both inherit.

Inheritance results in a better organization of code into smaller and simpler, easier to debug units.



Downsides

Storage Consumption
Inheriting a long chain of ancestors require greater memory usage. Your programming could easily represent less than one percent of the memory used.

Reliance on Common code
The inheritance relationship is tightly coupled. Child functionality depends on the inheritted members. Should the parent's method signatures or returns change then all child classes must change accordingly.



When to use Inheritance

When a strict parent-child relationship exists, and the relationship is over a number of children.



Prototype for extending a Base Class

class <derived_class_name> extends <base_class_name>



Example:

class Parallelogram extends FourSidedFigure





Explicit Access to the Base Class methods and variables
Suppose both your Parent class and Child class define the same method name along with the same signatures, but you wish to directly access the Parent class method.

You can force the access by use of the “super” qualifier.

To apply the Parent class's method or variable from the child class, you must qualify the name of the member with the name of the class with super.



super.getLength();

int rectWidth = super.width;





When the base class and the derived class use the same name and you want to ensure that you use the current class' method or property, then you can qualify the name of the method or property with the “this” qualifier.



this.getLength();

int rectWidth = this.width;





Instantiation Considerations
The Base or Super Class is inherited by all classes derived from it through the descendant chain.

During instantiation of a class object the ancestor classes are created and initialized first, then the final decendant class. This means that the super class' constructor will be executed prior to execution of the sub class' constructor. Calling the sub class constructor will cause a call by that constructor to the chain of the super class constructors.









To access an inheritance example: inheritancelab.java circleds.java sphereds.java globeds.java coneds.java cylinderds.java