A Java Primer


  1. Basic language characteristics
  2. A simple Java program
  3. Basic language elements
    1. Data types
    2. Strings
    3. Constants
    4. Variable declarations
    5. Identifiers
    6. Operators
    7. Expressions
    8. Statements
    9. Comments
  4. Methods
    1. Console output and input
    2. Command-line arguments
    3. Scope
  5. Using classes and objects
    1. Creating objects
    2. Using objects
    3. the Java class library
  6. Strings, Arrays, and Lists
    1. Strings
    2. Arrays
    3. Lists
    4. List methods
  7. Object-oriented programming
    1. Writing a class definition
    2. Visibility
    3. Static vs. non-static
  8. Inheritance
    1. Extending a class
    2. The Object hierarchy
    3. Assignment compatibility
    4. Abstract classes
    5. Interfaces
  9. Iterators
  10. Exceptions


Basic language characteristics


A simple Java program

public class HelloWorld {
    public static void main(String[ ] args){
        System.out.println("Hello, world");
    }
}

To run the code above from an operating system prompt:
  1. Save the code in a file called HelloWorld.java
  2. Compile the code using the javac command
  3. The output of the compiler is a file called HelloWorld.class
  4. Run the program using the java command
Java IDEs (Integrated Development Environments) such as Eclipse and DrJava combine the functions of editing, compiling, running, and debugging Java programs.


Basic language elements

Data Types

primitive type vs.
      reference type

examples

int x = 47;
String make = "Chevrolet";

Strings

A String is an immutable sequence of characters
String str1 = "abcde";
String digits = "0123456789";
Strings can be concatenated with the '+' operator
String vegetable = "Brussels" + "Sprout";
Strings can be concatenated with both primitive and reference types

Constants

For integers, the usual decimal notation is used.  Hexadecimal integer constants are preceded by 0x.

Single character constants are enclosed by single quotes.

Character string constants are enclosed by double quotes.  String constants are always stored with a '\0' as a terminating byte.

Variable declarations

Every variable must be declared.  The form of a declaration is
datatype variable-name;
examples
int sum;
float average;
double rating = 3.5;
boolean in;
Point x,y;
Declarations must appear within a class declaration

Identifiers

Operators

  1. Arithmetic operators

    +  -  *  /  % (mod) - (unary minus)

  2. Relational operators

    >  >=  <  <=  == (equals)  != (not equals)

  3. Logical operators

    &&  ||  !

  4. Increment and decrement operators
  5. ++ is a unary operator which adds 1 to its operand.  -- subtracts 1.  These operators may be used as prefixes or suffixes.  If used as a prefix, ++ increments its operand before it is used; if used as a suffix, ++ increments its operand after it is used.

  6. Bit-level boolean and shift operators

    &   bitwise and

    |   bitwise or

    ^   bitwise exclusive or

    <<  left shift

    >>  signed right shift

    >>> unsigned right shift

    ~   complement (unary)

  7. Assignment operators
  8. =  is the standard assignment operator.  Others can be formed by a combination of a binary operator (such as +,*,<<, etc.) and '='.  For example, a += b is equivalent to a = a+b.  The result of an assignment is the assigned value.  The variable on the left is changed as a side effect.  Thus, an assignment can be embedded within an expression.  For example, a = (b = c) stores the value of c in both a and b.

  9. Operator precedence (from highest to lowest)

Precedence

Operator

Associativity

1

(), []

non-associative

2

new

non-associative

3

.

left-associative

4

++, --

non-associative

5

- (unary), + (unary), !, ~, ++, --, (type)

right-associative

6

*, /, %

left-associative

7

+, -

left-associative

8

<<, >>, >>>

left-associative

9

<, >, <=, >=, instanceof

non-associative

10

==, !=

left-associative

11

&

left-associative

12

^

left-associative

13

|

left-associative

14

&&

left-associative

15

||

left-associative

16

?:

right-associative

17

=, *=, /=, %=, -=, <<=, >>=, >>>=, &=, ^=, |=

right-associative

Expressions

An expression is a construct made up of variables, operators, and method invocations that evaluates to a single value.

examples

200
200 + 1
x < y
(y >= x) && (z == w++)

Statements

  1. Any expression followed by a semicolon is an expression statement.  For example,

    x = 35;
    i++;
    area = Math.PI * radius * radius;
    System.out.println("Hello, world);

  2. Declaration statement

    <type> identifier;

    <type> identifier = <initial value(s)>;

    examples

        int x = 24;
        int w, z=10, u;
        double[ ] array2 = {3.5, 4.7, 6.2, 7.9, 11.2};
        Point2D p1 = new Point2D(3.5, 8.4);

  3. Block

    { statements }

    Any sequence of 0 or more statements within braces is a block.  Blocks are used for two reasons:


  4. if statement

    if (expression)
        statement

    if (expression)
       statement1
    else
       statement2

    examples

    if(y < 0)
        System.out.println("y is negative");
    else
        System.out.println("y is nonnegative");

    if(a == b){
        int x = a * b;
        int y = a + b;
        System.out.println(x+" "+y);
    }

  5. while statement

    while (expression)
        statement

    example

    while(s < 100){
        s += arr[i];
        i++;
    }

  6. do statement

    do statement
    while (expression);
  7. similar to while, but guarantees that the loop body is executed at least once

  8. for statement

    for (initialization; termination-test; increment)
         statement


    example

    for(int i = 0; i < 100; i++){
         sumsq += i*i;
    }

  9. switch statement

    switch (expression)
        {
           case constant : statement(s)
           case constant : statement(s)
          .
          .
          .
          case constant : statement(s)
         default : statement(s)   (optional)
       }
  10. switch is used as an alternative to a nested sequence of ifs

  11. return statement

    return;
    return expression;
  12. return from a method, possibly returning a value to the caller

  13. break statement

    break;

    terminate the execution of a loop or switch; branch to the statement immediately following the loop or switch

  14. continue statement

    continue;

    terminate the execution of the current loop iteration; branch to the test step of the loop

  15. empty statement

    ;

Comments


Methods

Functions in Java are called methods.

1. Signature - specifies the name of the method and its parameters
2. Body - defines what the method does

Declaring a method

[<modifiers>] <return type> <name>( <parameters> ) {
    // method body
}

example

 /**
  * Print a string multiple times
  * @param n number of times to print
  * @param s string to print repeatedly
  */
void printChars( int n, String s ) {
    for ( int i=0; i<n; i++) {
        System.out.print( s );
    }
}

printChars( 5, "happy" );


Methods can be overloaded; that is, we can write two different methods with the same name as long as they have different parameter lists.

void printChars( int n, char c ) {
    for ( int i=0; i<n; i++) {
        System.out.print( c );
    }
 }

printChars( 5, 'z' );

Console output and input

Java provides an object called System which connects to the local operating system.  It can be used for (among other things) console input and output.

System.out.println(String s);  // prints s, cursor moves to new line
System.out.print(String s); // prints s; cursor remains at end of s
System.out.printf(String format, item1, item2, ...); // prints items according to format (borrowed from printf in C)


examples

System.out.println("Hello, world");
System.out.println("The sum is "+x);
System.out.println(500);
System.out.printf("The sum is %d%n",x);
System.out.printf("The pitcher's ERA is %5.2f%n", era);

printf uses format codes as place holders for items in the item list.  The most common are



Input using System.in is normally done with a Scanner.  A Scanner is a Java object which performs conversions between character input and typed values (int, float, double, String, char).

The statement

    Scanner input = new Scanner(System.in);

creates a Scanner named "input" which will read from the standard input System.in.

The following Scanner methods can then be used to read from the Scanner:
Scanner must be imported from the package java.util with one of:
import java.util.Scanner;
import java.util.*;
Don't create more than one Scanner for the same input stream.
Don't mix next with calls to other methods.


Command-line arguments

When a program is loaded, arguments may be passed from the command interpreter to the main program.  The command line is parsed into distinct words, which are stored in an array of strings.  A reference to this array is passed to the main program as the parameter args.
static public void main(String[ ] args)

args is an array of Strings containing the words from the command line
args[0] is the first word from the command line
args[1] is the second word
args[2] is the third word, etc.

example  This progam prints its command-line arguments, one per line.

static public void main(String[ ] args){
    for(String arg : args)
        System.out.println(arg);
}


Scope

The scope of a variable determines where in the program that variable may be referred to simply by name.

Using classes and objects

Creating objects

syntax:

<type> <name> = new <type> ( <parameters> );

examples

Scanner scanner = new Scanner(System.in);
Point vertex = new Point(7.0, -4.0);
Picture window = new Picture(300, 200);
Color orange = new Color(255, 128, 0);

The names of classes are normally capitalized (e.g. Point, Color).

Strings are also objects, but can be instantiated with a String constant:

String name = "Amanda Jones";

Using objects

When an object is created with new, a reference to the object is returned.  The object's member variables and methods can be accessed through this reference, using dot notation.

syntax:

<reference variable> . <method name> ( <parameters> )
<reference variable> . <member variable name>

examples

String hello = "hello, world";
System.out.println(hello.length()); // print the length of a String

Point p1 = new Point(3, 4);
Point p2 = new Point(0, 0);
System.out.println(p1.distance(p2)); // print the distance from p1 to p2

Point vertex = new Point(3.0,4.0);  // create a Point with coordinates (3,4)
vertex.translate(2.0,-2.0);  // move the point 2 units in the x direction and -2 units in the y direction
System.out.println(vertex.x + " " + vertex.y);  // print the x and y coordinates of the point

the Java Class Library

An extensive collection of classes are found in the Java class library.  Documentation on these classes can be found at

http://docs.oracle.com/javase/7/docs/api/index.html

The library classes are structured into packages.  Some of the commonly used packages are

javax.swing -- includes classes for writing GUI interfaces, such as JFrame, JButton, JTextField, etc.
java.util -- includes collection classes such as ArrayList, Stack, HashMap, etc.
java.lang -- includes the String and Math classes, as well as the wrapper classes Integer, Double, Boolean, and Character
java.io -- includes classes for performing file input and output

Strings, Arrays, and Lists

Strings

A String is an immutable sequence of characters
String str1 = "abcde";
String digits = "0123456789";

Strings can be concatenated with the '+' operator
String vegetable = "Brussels" + "Sprout";

Strings can be concatenated with both primitive and reference types

A table of String functions:


action
str.charAt(3)
char at position 3 (4th char)
str.substring(2,5)
substring in positions 2-4 (excluding 5)
str.substring(2)
substring from position 2 through the end of the string
str.length()
number of characters in the string
str.indexOf('x')
first occurrence of character 'x'
str.indexOf("xyz")
first occurrence of substring "xyz"
str.startsWith("abc")
check if "abc" occurs at the beginning of str
str.split("\\s+")
split into array delimited by whitespace
str.split(",")
split around commas
str.trim()
remove leading/trailing whitespace
str.toUpperCase()
convert to upper case
str.toLowerCase()
convert to lower case
str1.equals(str2)
compare strings


Arrays

examples

double[ ] ratings = new double[100]; // creates an array of 100 doubles
int[ ] scores = {50, 30, 90}; // creates an initialized array of 3 ints




Point[ ] points = new Point[10]; // creates an array of 10 Point references; however, it does not instantiate any Points

Multi-dimensional arrays

declaration:
double[ ][ ] matrix = new double[10][15];
usage:
matrix[0][0] = 3.4;
double y = matrix[3][5]

Lists

Java supports two types of list:  ArrayList and LinkedList.  Both of these are classes which implement the List interface.

Like other objects, an ArrayList is created (i.e., instantiated) using the new keyword, as follows:

ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<String> words = new ArrayList<String>();

The class name in brackets (Integer, String) indicates the data type of the data which can be stored in the list.

List methods

Assume that the list has been created with T as the underlying data type.

boolean add(T item); // adds item at the end of the list. Returns true.

void clear(); // delete all the elements from the list.

boolean isEmpty(); // returns true if and only if the list is empty.

boolean remove(T item); // removes the given item if it is present in the list. Returns true if the item is actually removed; false if it is not present.

boolean contains(T item); // returns a boolean value indicating whether or not the item is present in the list.

int size(); // returns a count of the number of elements in the list.

T get(int index); // returns the item at the given position index in the list. The list is unchanged.

T set(int index, T item); // stores item at position index, replacing the T object at that position. returns the T object which is replaced.

void add (int index, T item); // inserts item at position index. Items to the right of index are shifted one position to the right to make room for this item.

T remove(int index); // removes and returns the item at position index. Items to the right of index are shifted one position to the left to fill the space left by the deleted item.

Object-oriented programming

In the object-oriented approach to problem solving, the problem domain is modeled with objects. Objects represent real or abstract entities in the problem domain.

example  Suppose we are writing a program to handle course registration at a college. As part of the program design process, we would identify objects which have some significance in the registration system, such as
(Identifying the objects for a given problem is not easy. A variety of tools and methodologies have been developed to help out, but it takes experience to be a competent designer. The design process typically requires several iterations before a design can be programmed.)

Objects with similar characteristics are grouped together into classes. In the registration example, we would have:

Objects:
Classes:
Each object in a class is called an instance of the class.  For example, the "CSCI 102" object is an instance of the Course class. Each Java object must be an instance of some class.

We've seen some examples of classes already:

When a object-oriented program is executed,

Writing a class definition

A Java programmer writes a class definition to describe each class used in a program. In fact, every Java program consists of a set of class definitions. Then, when the program is executed, instances of these classes (i.e., objects) are created.  The class definition serves as a template, or blueprint, for creating objects of the class. (Class is to cookie cutter as object is to cookie.)

A class definition describes the attributes (called member variables or fields) and behavior (that is, the methods) of objects in the class.

Again using the registration example, the Student class might contain:

attributes (what the student has)
behaviors (what the student does)
Each Student object has different values for its attributes, but they all have some value for each attribute. The set of attribute values of an object is called the state of the object. It is essentially a memory belonging to the object.

To write your own class definition, write a header with the name of the class.  The body of the class is enclosed in braces, and contains the class's fields, constructors, and methods:
class MyClass {

    field declarations

    constructor declarations

    method declarations

}

example  a Rectangle class

Visibility

Java supports four levels of visibility, which can be applied to variables and methods.

public
visible to code in any class
default
visible to code in the same package (this is the default for variables and methods)
protected
visible to code in the same class and its subclasses
private
visible to code in the same class only

A class can have either public or default visibility.

Static vs. not-static

Variables and methods in classes are either not static (the default) or static.


variable
method
static
One instance of the variable is shared by all objects of the class, so we use the term "class variable"
The method can be called independently of any objects in the class.  syntax:  ClassName.methodName(parameters);
example:  Math.random();
not static
Each object of the class has its own instance of the variable, so we use the term "instance variable"
The method can be called only using a reference to an object of the class.  syntax:  objectReference.methodName(parameters);
example:  list.add(element);


Inheritance

We've talked about the importance of reusability in software.  And we've seen this concept in action, as we've used code from the Java API such as Scanner, ArrayList, etc.  An important way that reusability is supported in Java (and object-oriented programming in general) is through the use of inheritance.  The idea is that we can modify a class by specializing it to a subclass.

example   animal --> mammal --> primate --> gorilla

example
  Vehicle  -->  SUV  -->  RAV4

vehicle class hierarchy diagram


Classes related by inheritance form an is-a relationship.  For example, a Truck is a (specialized type of) Vehicle.  Every gorilla is a primate, but not every primate is a gorilla.

Furthermore, there are some attributes that are shared by all gorillas that are not found in all primates.  So, a gorilla class would have all of the attributes of primates, but some additional ones that are specific to gorillas.  As a result, we say that the gorilla class inherits the attributes of primates.  Because the gorilla class has all of the attributes of primates plus some additional ones, we say that the gorilla class extends the primate class.  And we say that primate is the superclass of gorilla.  In Java, a class may have only one superclass, but may have many subclasses.

Extending a class

Technically, when a Java class is extended by inheritance, three types of extension are possible:
  1. Adding additional instance variables.
  2. Adding additional instance methods.
  3. Overriding an instance method; that is, replacing a method of the superclass with a method specific to the subclass.
example  A class representing a numeric progression; that is, a sequence of integers with a starting value and a rule that determines the next value.  The class has one instance variable representing the current value in the sequence, and methods firstValue() and nextValue().

class Progression {

    protected int first, current;

    Progression()
    {
        first = current = 0;
    }

    protected int firstValue(){
        current = first;
        return current;
    }

    protected int nextValue() {
        return ++current;
    }

}

This class defines the progression 0, 1, 2, 3, ...

Q:  How can Progression be extended to a general arithmetic progression class?  a geometric progression class?  a class representing a Fibonacci sequence?  Here is the Java code for Progression and three examples of extensions of Progression, along with a JUnit test case:

Progression.java

ArithProgression.java


GeomProgression.java


FibonacciProgression.java


ProgressionTest.java



The Object Hierarchy

The extends relationship imposes a hierarchy, or tree structure, on Java classes.  For example, GUI components are all subclasses of Component, which itself is a subclass of Object.

Java defines a class called Object which is the root of the tree.  Every class definition which does not explicitly extend another class, implicitly extends Object.  So, every class (except Object) has a superclass from which it inherits.  Among the methods that every class inherits, directly or indirectly, from Object are
boolean equals (Object);
String toString();
These methods are often overridden in a class definition to code that is specific to the class.  However, it means that you can call the toString method of any object.

Assignment compatibility

Consider the class hierarchy of vehicles shown above.

Q:  If we have a variable of type SUV, can we store an Explorer object in it?  That is, could we write
SUV suv = new Explorer();
A:  Yes because an Explorer is an SUV (albeit a special type of SUV).

Q:  What if we try to do this in reverse:
Explorer exp = new SUV();
A:  We get an error.  We cannot store an SUV object in an Explorer variable.

Some implcations of this:
  1. If we have an array of SUVs defined by
    SUV suv[] = new SUV[50];
    we could store Explorers, Cherokees, 4Runners, etc. in the array.  The same thing applies to generic classes like ArrayList.

ArrayList<SUV> suvList = new ArrayList<SUV>();
suvList.add(new Explorer());


  1. If we have a method that expects an SUV as a parameter, we can pass an Explorer object to it.  

One result of this is a potential ambiguity.  Suppose that SUV has a "drive" method, which is overridden by Explorer.  Suppose we say
SUV suv = new Explorer();
then
suv.drive();
Which drive method is called, SUV's drive method or Explorer's drive method?

Abstract classes

An abstract class is a class in which some or all of the methods are abstract; that is, a header line for the method is provided, but not a method body.  It is used when it is desirable to create a superclass for a group of related classes.

example  A Shape abstract class

abstract class Shape {
   double posX; // x-coordinate of this shape's position
   double posY; // y-coordinate of this shape's position
  
   Shape(double x, double y){
      posX = x;
      posY = y;
   }
  
   void move(double dx, double dy){
      posX += dx;
      posY += dy;
   }
  
   abstract double perimeter();
   abstract double area();
}


Now, we can define specific shapes, such as:

class Rectangle extends Shape {
  
    double length, width;
   
    Rectangle(double cornerx, double cornery, double length, double width){
       super(cornerx, cornery);
       this.length = length;
       this.width = width;
    }
   
    double perimeter(){
       return 2*length + 2*width;
    }
   
    double area(){
       return length * width;
    }
}

class Circle extends Shape {
  
    double radius;
   
    Circle(double centerx, double centery, double radius){
       super(centerx, centery);
       this.radius = radius;
    }
   
    double perimeter(){
       return 2 * Math.PI * radius;
    }
   
    double area(){
       return Math.PI * radius * radius;
    }
}

An abstract class cannot be instantiated, but it defines a data type, which can be used to declare variables.  Here is an example of how an abstract class can be used in application code:
 
ArrayList<Shape> shapeList = new ArrayList<Shape>();

     
shapeList.add(new Circle(0.0, 0.0, 1.0));
shapeList.add(new Rectangle(2.0, 2.0, 2.0, 5.0));
shapeList.add(new Circle(10.0, 10.0, 2.5));
shapeList.add(new Rectangle(3.0, 4.0, 6.0, 4.0));
shapeList.add(new Rectangle(2.0, 7.0, 3.0, 5.0));
     
double areasum = 0.0;
for(Shape s : shapeList){
   areasum += s.area();
}
System.out.println(areasum);

Interfaces

An interface takes the idea of an abstract class one step further.  In an interface, there are no variables, and all of the methods are abstract.  As a result, the definition of an interface consists only of a set of method headers.  A class is said to implement an interface if it contains implementations of all of the interface's methods.  Java uses interfaces to support the concept of an abstract data type (ADT).  Consider the following:

interface

The key idea here is that the interface separates the applications of an ADT from its implementation. As long as the application and the implementation agree on the interface, they don't need to know anything else about each other.  This makes it possible to
This model is used throughout computer science, not just in object-oriented programming or data structures.  Consider for example, Intel's x86 architecture. The architectural specifications are published by Intel and form an interface between the CPU hardware and the operating system software.  As a result,
Application designers are freed from knowing anything about the details of the implementation.  They can trust the library code to obey the interface. Implementers are freed from knowing anything about the details of any application.  As long as they program the implementation so that it satisfies the interface correctly, they've done their job.

Like abstract classes, interfaces cannot be instantiated, but they can be used as data types.

the Java Collection Framework

The Java Collection Framework is a set of classes and interfaces in the Java API is to define collections.  A collection is an object whose purpose is to hold other objects; ArrayList is one example of a collection.  Others are LinkedList, Stack, Queue, and Map, which we will study later in the course. Each of these uses a different data structure to organize the objects it holds.

Some examples:

interface
implementing classes
List
ArrayList, LinkedList
Queue
ArrayDeque, PriorityQueue
Set
HashSet, TreeSet
Map
HashMap, TreeMap


Iterators

An iterator is an object used to step through a list or collection sequentially.  It is an abstraction of the normal method of stepping through an array or ArrayList, but works on other kinds of collection, too, including LinkedList

As defined in Java, Iterator<T> is an interface with three methods:

boolean hasNext(); // returns true if and only if there are more elements in the collection
T next();  // returns the current element in the collection, and advances to the next
void remove();  // remove from the collection the item which was most recently returned by next()

ArrayList and LinkedList support the use of Iterators by implementing another interface called Iterable<T> which has one method:

    iterator();  // returns an Iterator for this collection 

example  Print the contents of an ArrayList of Strings using an Iterator


ArrayList<String> list;

Iterator<
String> i = list.iterator();

while(i.hasNext()){
    System.out.println(i.next());
}

example  Remove the negative integers from a ArrayList of Integers

   
ArrayList<Integer> ilist;

Iterator<Integer> i = ilist.iterator();
while(i.hasNext()
{

    int x = i.next();
    if(x<0)
        i.remove();
}

A collection which implements Iterable can be used in a for-each loop.


Exceptions

An exception is an unusual or unexpected event that occurs during the execution of a program.  Java treats exceptions as objects, and gives names to classes of exception.  We've seen a few, such as FileNotFoundException and IndexOutOfBoundsException.  Some of you have seen the NullPointerCheckingException.

Catching an exception

When an exception occurs, Java normally terminates the program and prints a stack trace.  However, a program can anticipate exceptions and handle them itself, by using a try-catch statement.  A try-catch statement consists of a try block followed by one or more catch blocks.

syntax:

try {
  <statements>
}
catch(<exception-type> <identifier>){
   <statements>
}
...

When a try-catch statement is executed:

Throwing an exception

A program may itself check for unusual conditions (possibly specific to the spplication) and, if one occurs, throw an exception.  This is done with a throw statement.

syntax:

throw <expression-object>

The exception is then handled like any other exception.  It can be caught by some other part of the program, or it can be thrown to the Java runtime system.

the throws clause

Java requires that certain types of exception be either explicitly caught or thrown (rather than falling back on the default behavior, which is to terminate the program).  If a method doesn't catch the exception, it must say so by saying that it throws the exception with a throws clause.  This clause occurs is written after the method header and prior to the left brace enclosing the method body.

example:

public void someMethod() throws FileNotFoundException {