Module 2: Elementary Java, Part I


Java Syntax


Comments in Java

There are three types of comments in Java:

  1. In-line comments, using // that comment out everything up to end of the current line.
  2. Block comments (C-style) using /* and */ that comment out everything in between.
  3. Documentation comments using /** and */ that are used by the javadoc utility to produce documentation.

The following example demonstrates each kind: (source file)


// This is an in-line comment. It ends at the end of this line.

// This attempt to roll to the next 
line will fail to compile.

/* Instead, long comments are best
   placed inside block comments
   like this */

/** 
 * Finally, there is the type of documentation that
 * javadoc produces. To use this, you need to use javadoc
 * commands inside the comment block, such as:
 * @version 1.1
 * @author Rahul Simha
 * @return No value returned
 * @param  command arguments (any number of strings)
 * Note: each line must start with a `*' symbol.
 */

// javadoc will produce HTML documentation. To try it out, don't
// forget to fix the in-line comment error above.

public class helloworld3 {
  public static void main (String[] argv)
  {
    System.out.println ("Hello World!");   // prints to screen
  }
}

Built-in data types:

Java has 8 pre-defined types:

  • 4 integer types: byte, short, int, long
  • 2 real types: float, double
  • 1 boolean type: boolean
  • 1 character type: char

Let's consider each of these in turn:

  • byte
    • 1 byte of storage.
    • Range: -128 to 127.

  • short
    • 2 bytes of storge.
    • Range: -32,768 to 32,767.

  • int
    • 4 bytes of storage.
    • Range: -2,147,483,648 to 2,147,483,647.

  • long
    • 8 bytes of storage.
    • Approx. range: -9 x 10^{18} to 9 x 10^{18}.
    • long literals should end with an L, as in
    •          deficit = 1000000000L;
         

  • float
    • 4 bytes of storage.
    • Approx. range: +/- 3.40282347 x 10^{38}.
    • 6-7 digits of accuracy.
    • float literals end with a F.
    • If a real-valued literal does not end in F, it's assumed to be a double

  • double
    • 8 bytes of storage.
    • Approx. range: +/- 1.7 x 10^{308}.
    • About 15 digits of accuracy.

  • boolean
    • Not specified
    • Values are true and false.
    • Unlike in C/C++, you cannot treat a boolean as an int

  • char
    • 2 bytes of storage.
    • Stored in Unicode
    • Unicode characters are represented by the escape sequence \uxxxx where xxxx is a 4-digit hex number.
    • Java supports standard C escapes like \n, \b, \f, \r, \\, \", \' and \t.


Identifiers in Java

  • Any sequence of letters or digits, beginning with a letter.
  • Case is significant.
  • All characters are significant.
  • For letters, any Unicode character representing a letter will do.


Getting started with writing Java

Before we get to objects, functions and the like, let's first worry about writing simple statements in a single function

To do this, use the main function as in helloworld, only we will call the file test.java.

Turns out, the class name must also be called test

Rule: Your Java source file (e.g., helloworld.java) can have many class 'es, but at least one class must have the same name (helloworld ) as the file and that class must have a main function if you want to execute the class directly. The program will start execution in that main function.

public class Test {
  public static void main (String[] argv)
  {
    // Put your code in here
  }
}

In-class exercise 2.1: What happens if you do not have a main function in your file? Try compiling and executing such a file.


Variables and assignment

Variables are declared by following the type keyword with the identifier:

  byte b;                 // A byte
  int i;                  // i is a 4-byte integer
  long num_stars;         // A long integer
  float epsilon, delta;   // Multiple variables separated by a comma      
  double                  // Often, you use several lines for commenting:
    pi,                   // 3.14159
    e,                    // 2.718
    squareRootOfTwo;      // Use Math lib for computing this
  boolean over;

Assignment uses the assignment operator =

  int i, j;
  i = 7;
  j = 2000;

Variable declarations can occur almost anywhere in a block of code.
Declarations and assignment can be combined where appropriate:

  double pi = 3.14159;         // Declaration and assignment combined
  int i = 3;
  double threePi;              // Pure declaration

  while (true) {
    threePi = i * pi;          // Pure assignment
    double fourPi  = pi * 4;   // Combination in a sub-block of code
  }

NOTE:


Constants

Constants in Java are a little strange.
Currently, the only way to declare a constant is as follows:

public class Test {

  public static final double pi = 3.14159;

  public static void main (String[] argv)
  {
    double d = pi;
  }
}

NOTE:


Conversions and casting

Can the contents of an int variable be copied into a (assigned to) long variable? (Yes).

Can an doublebe assigned to a double? (Not directly).

For example:

   int i = 5;
   long j;
   double d = 3.141;

   j = i;              // Fine - an example of an implicit cast.
   i = d;              // Won't compile - needs an explicit cast.
   d = i;              // Fine (implicit cast).

To assign a variable of one type to another, use a cast. A cast is the desired type in brackets, preceding the variable that needs casting.

   int i = 5;
   long j;
   double d = 3.141;

   j = (long) i;              // Not really needed.
   i = (int) d;               // Truncates the real value;
   System.out.println (i);    // Prints `3'

NOTE:

  • The compiler implicitly casts assignments up this hierarchy:
  • byte -> short -> int -> long -> float -> double

  • Explicit casts are allowed only between compatible types: you cannot cast a boolean to an int, for example.
  • You can (and sometimes need to) explicitly cast between char's and int's.

  • Casts can be used in any expression, e.g., function calls (very useful):
  • public class test {
      // A function that prints an integer
      public static void print (int i)
      {
        System.out.println (i);
      }
    
      public static void main (String[] argv)
      {
       double d = 3.141;
       print ( (int) d);
      }
    }
       


Operators

Java supports standard C-style operators, for example: (source file)

public class TestOperators
{
  public static void main (String[] argv)
  {
    int i = 5;

    i = i + 1;
    i += 1;            // Same as i = i+1;

    // Pre and post-use increment
    i = 10;
    System.out.println (++i);    // Prints 11
    i = 10;
    System.out.println (i++);    // Prints 10

    // Comparison operators: < > <= >= == !=
    int j = 10;
    if (i != j)
      System.out.println ("Help! i not equal to l!");

    // Casting
    byte b = 8;
    long l = 100;
    i = i + b;         // b is automatically converted to an int
    i = i + l;         // Illegal - explicit cast required
    i = i + (int) l;   // OK (explicit downward cast)
    b = b + 1;         // Illegal: `1' is an integer
    l = l + 1;         // OK, `1' is up-cast.
    b++;               // OK, within type.

    // Bitwise operators: & | ^ << >> >>> &= |= ^= <<= >>= >>>=
    int x1 = 8, x2 = 15;
    int x3 = x1 & x2;
    System.out.println (x3);  // What does this print?

    // Boolean type
    boolean tired = true;
    boolean had_enough = true;

    // Boolean operators: && || !
    if (tired && had_enough)
      System.out.println ("Go home");
  }

}

Complete list of operators:

  • Unary operators: +, -
  • Post- and pre-increment: ++, --
  • Standard arithmetic operators: +, -, *, /
  • Integer operators: / (div), % (mod)
  • Arithmetic assignment-and-operator shortcuts: +=, -=, *=, /=
  • Comparisons: == (equals), != (not equals), <, >, <=, >=
  • Boolean: && (and), || (or), ! (not), ^ (XOR)
  • Bitwise: & (and), | (or), ~ (complement), ^ (XOR)
  • Shift: <<, >>, >>>
  • Assignment shortcuts for bitwise and shift operators
  • String operator: + (concatenation)
  • Object operators: instanceof, . (Dot operator, for referencing components).
  • Miscellaneous: ?: (ternary conditional operator)


Strings

  • Java contains some (but, some would say not enough) support for strings.
  • Java strings are not basic types, but are actually sort-of objects.
  • String objects are special in that they have an operator, +, for concatenation.
  • Strings are immutable. You cannot change a string; you can modify a string only by creating a new one.
  • A number of string manipulation functions are provided.

Example: (source file )

public class TestStrings {

  public static void main (String[] argv)  // Actually, an array of strings
  {
    // Definition
    String m = "Yes, I had tea in the Oval Office that Monday";
    String b = "What is the definition of tea?";

    // Printing
    System.out.println ("Monica: " + m // Note concatenation
                        + "\n" +       // Expressions can spill over
                        "Bill: " + b); // lines but strings may not.

    int i = b.length(); // length() method returns # chars in string

    System.out.println ("String \"" // Note backslash-quote
                        + b + "\" has length " 
                        + i  // Automatic conversion to string
                        + " chars");

    // Assignment
    String b2 = b;     // Actually, a pointer. But since strings are
                       // immutable, there's no problem.
    System.out.println ("b2: " + b2);

    // Modifying strings using String methods
    String b3 = b.substring (0,6);  // First 7 letters
                                    // Must extract into a new string
    System.out.println ("b3: " + b3);

    // Extracting individual characters
    char c1 = b.charAt (0);
    char c2 = b.charAt (2);
    System.out.println ("c1+c2: " + c1 + c2);

    // Testing equality
    if (b2.equals(b))
      System.out.println ("b2 equals b");

    // Short-cut operator:
    b2 += b2;                 // Concatenate a string with itself.
    System.out.println ("b2: " + b2);

  }
}

The String class contains many useful functions:

  • Case conversion.
  • Removing leading and trailing whitespace.
  • Searching for substrings.
  • String comparison (alphabetical).


Control flow statements

Java's control flow statements are the same as those in C/C++ except:

  • There is no goto.
  • Java has something called a labelled break.

Let's go through the standard control flow statements:

  • if-statement:
  •       if (i == 4) 
            System.out.println ("Four");
    
          if ( (i >= 4) && (i <= 8) ) {
            j = i;
            System.out.println ("Between 4 and 8");
          }
       

    In-class exercise 2.2: Find out what happens if you use an assignment in an if-expression, e.g.,

    
      if (i = 4) {
          System.out.println ("Four");
    }
    

  • if-else statement:
          if (i < 4)
            System.out.println ("Less than four");
          else if (i == 4)
            System.out.println ("Exactly four");
          else 
            System.out.println ("More than four");
       
    Although braces were not required above, it's often considered a good habit to always use them:
          if (i < 4) {
            System.out.println ("Less than four");
          }
          else if (i == 4) {
            System.out.println ("Exactly four");
          }
          else {
            System.out.println ("More than four");
          }
       



  • while-loop:
  •        i = 4;
           while (i > 0) {
             System.out.println (i);
             i = i - 1;
           }
       

  • do-while-loop: (left as an exercise)
  • for-loop:
  •       int i;
          for (i=1; i<=10; i++)
            System.out.println (i);
    
          for (int j=1; j<=10; j++) {  // Note definition of j
            i = i + j;
            System.out.println (j);
          }
          // j is not available here
          System.out.println (i);      // What gets printed out?
       

    Note: Comma-separated statements and expressions may appear in the first and third parts of the for-loop construct.

  • switch statement:
    Instead of
  •       if (i == 4)
            System.out.println ("Four");
          else if (i == 3)
            System.out.println ("Three");
          else if (i == 2)
            System.out.println ("Two");
          else if (i == 1)
            System.out.println ("One");
          else
            System.out.println ("Not interesting");
       

    write

          switch (i) {
            case 4: 
              System.out.println ("Four");      
              break;                         // The break is needed to
                                             // avoid falling to next case.
            case 3: 
              System.out.println ("Three");      
              break;
            case 2: 
              System.out.println ("Two");      
              break;
            case 1: 
              System.out.println ("One");      
              break;
            default:
              System.out.println ("Not interesting");
          }
       

  • unlabelled break: usually, to break out of a loop
  •       while (true) {  // Initially an infinite loop;
            // Stuff
            ...
            // Read integer from user
            if (i == -1) break;
            // Other stuff
            ...
          }
          // Control reaches here on break
       

  • labelled break:
  •     outerloop:        // Label set up here, BEFORE loop starts.
          while (true) {  // Initially an infinite loop;
            // Stuff
            ...
            // Read input from user
            while (true) {
              // Read one character at a time.
              if (invalid (c))
                break outerloop;
            }
            // Other stuff
            ...
          }
          // Control reaches here on break
       

  • try statement: we will cover this later when dealing with exceptions, but briefly, here's what it looks like:
  •       try {
            // Stuff
            ...
          }
          catch (Exception e) {
            // Deal with exception here
            System.out.println (e);
          }
       

  • Assignment expressions: The assignment operator can be used in expressions:
  •       
        int i = 5, j= 6, k = 7;
        System.out.println ( (i = j = ++k) );
       


Unidimensional arrays

  • Like String's, arrays in Java are "sort-of" objects.
  • They are similar to dynamic arrays in C++.

Let's look at some examples: ( source file)

public class TestArray {

  public static void main (String[] argv)
  {
    // Declaration: A is an array of int's
    int[] A;
    
    // The new operator instantiates an array with a given size.
    A = new int[10];

    // Individual items are referred to using square brackets.
    // Indexing starts from 0.
    for (int i=0; i<10; i++)
      A[i] = i;
    
    // This will compile but create a runtime exception.
    A[10] = 5;
    
    // A.length is a field indicating the length.
    System.out.println ("Number of elements of array A: " + A.length
                        + "\nContents:");
    
    // Size can be determined dynamically.
    int size = 10;
    double[] B = new double[size];
    
    // Arrays can be initialized
    String[] C = {"Michael", "Scottie", "Toni", "Dennis", "Luc"};
    
  }
}

In-class exercise 2.3: Write a program that takes in command line arguments, prints out each argument, the length of each argument and the average length of all the arguments. Name your program TestCommandLine Here's sample output:

% java TestCommandLine aaa aaaa
Arg#0 = aaa, length = 3
Arg#1 = aaaa, length = 4
Average: 3.5


Multidimensional arrays

  • Multidimensional arrays can be declared in a number of ways.
    (By declaring some sizes statically and assigning other dimension sizes dynamically).
  • We will consider only the most flexible case here: when all dimensions are dynamically assigned.
  • Referring to an element is straightforward:
    e.g.,
    A[7][19][4] is a particular element in a 3D array.
  • Array creation is a little more complicated.
  • First, consider 2D arrays.
    Think of a 2D array as an array of (unidimensional) arrays.

Example: let's create the identity matrix. (source file)

public class Test2DArray {

  public static void main (String[] argv)
  {
    int size = 5;
    int[][] identMatrix;

    // Create the first dimension - an array
    identMatrix = new int[size][];

    // Create the second dimension - an array for each 
    // element of the first dimension.
    for (int i=0; i < size; i++)
      identMatrix[i] = new int[size];   // The size can be changed
                                         // dynamically.

    // We're done creating the 2D array. Now create the
    // identity matrix and print it out.
    System.out.println ("Identity matrix of size: " + size);
    for (int i=0; i < size; i++) {
      for (int j=0; j < size; j++) {
        if (i == j) 
          identMatrix[i][j] = 1;
        else 
          identMatrix[i][j] = 0;
        System.out.print (identMatrix[i][j] + " ");
      }
      System.out.println ();
    }
  }
}

Since the 2D array is really an array of unidimensional arrays, the individual unidimensional arrays can be of different sizes.

The following example creates a triangle of 1's and prints it out: (source file)

public class Test2DArray2 {

  public static void main (String[] argv)
  {
    int size = 5;
    int[][] triangle;

    // There are `size' rows.
    triangle = new int[size][];

    // Each row has a different number of elements.
    for (int i=0; i < size; i++)
      triangle[i] = new int[i+1];

    // Compute elements
    System.out.println ("Triangle of 1's:");

    for (int i=0; i < size; i++) {

      // Count enough blanks for i-th row.
      for (int j=0; j < size-i; j++)
        System.out.print (" ");

      // Print out 1's. Note length reference as an alternative.
      for (int j=0; j < triangle[i].length; j++) {
        triangle[i][j] = 1;
        System.out.print ("1 ");
      }

      System.out.println ();
    }
  }
}

In-class exercise 2.4: Compile and execute the above program. Then, modify the above code to create and print Pascal's triangle. Sample output:

     1 
    1 1 
   1 2 1 
  1 3 3 1 
 1 4 6 4 1