Title: Fundamentals
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Fundamentals

What's So Great About Java:

1. Java is portable. The same Java code can run on all platforms supporting java. We give such code the name 100% pure java. It is possible to write non-portable java. But in general java is a lot more portable than other languages such as C.
2. Execution Environment is protected - The Java Virtual machine does not allow you to directly access memory through pointers. Breathe a sigh of relief to all of you C programmers that have crashed your application by writing into memory that didn't belong to you, or trashed the memory chain by freeing up a bad memory pointer.
3. Java is Compact - Download an applet and find out how big it is. If you compare the size with the equivalent Active-X control or MFC application you see a huge difference in size.
4. Java provides some very powerful libraries - You can do a lot with a small amount of code because of the power in the java libraries. Again comparing the size of the code for MFC versus Java and you will see that it is a lot easier working with Java.
5. J2EE (Server Side Java) - There is a lot of momentum today associated with using Java on Servers. Java Server Pages, Java Servlets, XML capabilities are all hot areas today and gaining a lot of momentum in the Non-Microsoft world. One of the reasons Microsoft is so hot to push ".NET" is related to trying to slow down the J2EE momentum.
6. Java in a Browser is very well protected from Viruses - Java Applets can only do what the browser allows. In particular applets have no direct access to memory or disk. Active-X does have such access. Yes Active-X does have more functionality because it has access to the whole machine. However, Active-X is a good opportunity to some enterprising Virus hacker on the web. Yes Microsoft has safeguards, but a Microsoft bug can quickly open the Virus floodgates.
7. Everything is an object - Well almost everything anyway. It takes some learning, but object oriented programming can be good to you once you get used to it. I used to have a negative attitude about Object Oriented programming, but once you get over the hump it's worth the effort.
8. Java Doesn't Allow Error Prone Things - Although Java looks like C, there are some notable omissions that seem to be related to eliminating common errors.
9. Java is Fun - Clem's opinion

Getting Started:

Java runs on all platforms. In this class we are going to use both Linux and a PC. The Linux account will require minimum setup work for you, and you can access from anywhere on the Internet.

We will also discuss installation of Java on a PC.

Click on the Setup/Start Up link to learn the setup procedures on Linux and on a PC.

In this section we will be covering Language fundamentals. If you want additional reading material on language fundamentals, check out:

Java.sun.com tutorial - Language section

Source Files

Java programs must end with the suffix .java.

If you create a class named Calculate (we will talk define public class later), then your filename must be named
Calculate.java - and java is case sensitive

If your program does not contain any public classes, then the name can be anything as long as it ends in ".java". For example:
xyz.java

Compilation occurs with:
javac Calculate.java

Executing a program is usually something like:
java Calculate

Basic Template for a Java class


class Rectangle
{
   double width=1.0;
   double height=2.0;
   static int numRectanglesCreated = 0;

   Rectangle()
   {
       numRectanglesCreated += 1;
   }
   Rectangle(double h, double w)
   {
       height = h;
       width = w;
       numRectanglesCreated += 1;
   }
   // Note this method is static --- note how it is called in main
   static double calcArea(double height, double width)
   {
      return height * width;
   }
   double getArea()
   {
       return height * width;
   }
   public static void main (String arguments[])
   {
    Rectangle r1 = new Rectangle();
    Rectangle r2 = new Rectangle(12.0, 14.0);

    System.out.println("area of r1 = "+ r1.getArea());
    System.out.println("area of r2 = "+ r2.getArea());

    System.out.println("area of height=7 and width=8 =" +
    	Rectangle.calcArea(7.0, 8.0));

    // Note that while I am inside the Rectangle class, the above statement
    // could be coded as:
    System.out.println("area of height=7 and width=8 =" +
    	calcArea(7.0, 8.0));
	
    System.out.println("Number of Rectangles created = " +
    	numRectanglesCreated);
   }

}


Identifiers

- contain letters, numbers, $ and _
- Identifiers can't start with a number




int 99year; // invalid
int year99; // valid
int hello#; // invalid
int $hello$; // valid
int MAX_VALUE; // valid


- Java is case sensitive.
- In general Java is not sensitive to whitespace: extra spaces, tabs, and carriage returns

Primitive Data Types

Java does not support Pointers, Unions or structures. Everything in java is a class unless it is one of the following primitive types.

Type | Size/Format | Description | Min Range | Max Range
(integers)
byte | 8-bit two's complement | Byte-length integer | -2^7 | 2^7-1
short | 16-bit two's complement | Short integer | -2^15 | 2^15-1
int | 32-bit two's complement | Integer | -2^31 | 2^31-1
long | 64-bit two's complement | Long integer | -2^63 | 2^63-1
(real numbers)
float | 32-bit IEEE 754 | Single-precision floating point | not needed | not needed
double | 64-bit IEEE 754 | Double-precision floating point | not needed | not needed
(other types)
char | 16-bit Unicode character | A single character | Not Applicable | Not Applicable
boolean | true or false | A boolean value (true or false) | Not Applicable | Not Applicable

In addition, there are classes that encapsulate the primitive types. These classes basically provide a mechanism to provide utility/conversion software for each of these types. Note that the description of what is provided with these classes can be found in the Java Documentation. We will demonstrate these classes later, but for now they are listed below (Note that the classes start with a captital while the primitives start with a lower case letter):
1. Byte
2. Short
3. Integer
4. Long
5. Float
6. Double
7. Boolean
8. Character

Variable Declarations and Identifiers

Declaring Variables have the following associated parts:

1. public, private, protected, or none (default)

2. final, static, transient, and volatile (optional)

3. variable type (int, boolean, String, and so on)

4. an identifier

Examples:
public int users=10;
public final int users;
static int a=3, b, c=a;
public Dimension d= new Dimension(20,100);
private String name= "Robert A. Heinlein";

Timing of Global Initializations:

When you declare a variable at the top of a class as a global variable you can optionally initialize it. This potential initialization occurs before the Constructor has been called. This can be illustrated with the following example:

class Check
{
int a=5;
Check()
{
    System.out.println("Constructor: a = " + a);
}
public static void main(String[] args)
    {
       Check c = new Check();
    }
}


Literal Values

Consider the Initializing with the following Literal Values:


class Measurement {
// Let all of the variables default.
  boolean t1, t=true, t2=false;
  char c='A';
  byte b=55; // decimal
  short s=0x20; // hex equivalent to 32 decimal
  int i = 020;  // octal equivalent to 16 decimal
  long l =0xFFFF; // hex
  float f=123.456F; // Note the F to make a float literal.
                    //The default is double and
                    //we will discuss this later
  double d=123.456; // double
  Integer I = new Integer("123"); // Integer Class


  void print() {
    System.out.println("Defaulted Values\n");
    System.out.println(
      "Data type      Default value\n" +
      "boolean        "  +  t + "\n" +
      "char           "  +  c + "\n" +
      "byte           "  +  b + "\n" +
      "short          "  +  s + "\n" +
      "int            "  +  i + "\n" +
      "long           "  +  l + "\n" +
      "float          "  +  f + "\n" +
      "double         "  +  d  + "\n" +
      "Integer        "  +  I  + "\n");
  }

  public static void main(String[] args)
  {
    Measurement d = new Measurement();
    d.print();
  }
 }



Uninitialized Variables

Normally, you want to initialize variables before they get used. However, Java provides initial values for global class variables. Try out the following example:


class Measurement {
// Let all of the variables default.
  boolean t;
  char c;
  byte b;
  short s;
  int i;
  long l;
  float f;
  double d;
  Integer I;


  void print() {
    System.out.println("Defaulted Values\n");
    System.out.println(
      "Data type      Default value\n" +
      "boolean        " + t + "\n" +
      "char           " + c + "\n" +
      "byte           " + b + "\n" +
      "short          " + s + "\n" +
      "int            " + i + "\n" +
      "long           " + l + "\n" +
      "float          " + f + "\n" +
      "double         " + d  + "\n" +
      "Integer        " + I  + "\n");
  }

  public static void main(String[] args)
  {
    Measurement d = new Measurement();
    d.print();
  }
 }



Local variables are a different story. Try moving the declarations of the variables inside the print routine.

Note that we actually stuck the Integer class as a variable that had a null instance. Even though I can print the value of "I" without a problem, I can't call one of the methods of "I". Try adding:
I.longValue();

To guard against using a null pointer error, you can add an if statement:
if (I != null) I.longValue();

Methods:(i.e. a Procedure or Function)

A method can be simple such as:

double getprice(int itemCode, Color itemColor){ }

or it can have a lot of modifiers attached to it and look like:

public static final synchronized double getPrice(
final int itemCode, Color itemColor) throws Exception { }

1. Access modifiers—public, private, protected, or none (default)

2. Special modifiers—abstract, final, native, static, or synchronized (optional)

3. Return type—a variable or void

4. Name of method (identifier)

5. Arguments passed to the method within ( ) brackets (none or many)

6. Exceptions thrown (optional)

7. Curly braces

In general the order of these keywords is significant. However, the order of the first 2 items can be interchanged.

String and println methods

We will have a lot more to say about strings throughout this course, but its helpful to give some fundamentals. Java made the String class real easy to work with.

String concatentation:
String str ="Clem ";
str = str + "Hasselbach";

Also its real easy to convert almost anything into a string. When you combine anything else with a string and use concatenation, Java will convert the other variable into a string:
String str="Value =";
double d=1.23;
str += d; // This is equivalent to str = str + d;

There is an always present object named System that contains another object named out. The out object has 2 very useful methods: print and println. Both methods take a string and print it to the default output device (your screen usually). The only difference between print and println is that println tacks on a new line at the end.
String str = "Fred Flinstone ";
long year=-5000;
System.out.println(str);
System.out.println("Lives in Rockville in the year " + year);

public static void main(String[] args)

Get used to seeing a method named main defined as above. Don't try to change that declaration or you will probably get something different than what you expected. Here is the scoop:

- A class does not need a method named main if your class is called from the java program.
- If you want to call a class from the command line, the java program expects your class to have a method named main declared as above.
- The method must be public and static to allow your program to access the class without first creating an instance of your class.
- Any arguments typed in on the command line are passed in the String array called args. We will talk about this later.

Consider the following program:


class Simple {
  public static void main(String[] args)
  {
    String str = "Fred Flintstone";
    double year = -5000;
    System.out.println(str);
    System.out.println("Lived in the year " + year);
  }
 }



Make sure you save this in a file named Simple.java

Compile it with:
javac Simple.java

Execute it with:
java Simple

Static Variables

- Static variables are kind of like global memory.
- Static variables are not part of any Object instance.
- Normal variables are always accessed through an object instance handle


class Person
{
  static int person_count = 0;
  String name;
   Person (String n)
   {
      name = n;
      person_count += 1;
   }
   String getName()
   {
    return name;
   }
   public static void main(String[] args)
   {
      // p1, p2 and p3 are instances of the class Person
      Person p1=new Person("George");
      Person p2=new Person("Fred");
      Person p3=new Person("Clem");

     // To reference any non-static entity in a Person class, you must
     // access it through the class instance handle

      System.out.println("Person 2 using getName()= " + p2.getName());

      // Another way you can access the name
      System.out.println("Person 2 using the variable = " + p2.name);

      // person_count is not part of any Person instance.  Its kind of like global memory
      System.out.println(" We have created "+person_count + " people");
   }
}


Static Methods


class MyTrig
{
// Note that the Math class in java.lang is loaded
// with static methods and constants --- check it out
   static double deg2rad(double ang)
   {
      return ang * Math.PI /180.0;
   }
   static double sin_deg(double ang)
   {
      double ang_radians = deg2rad(ang);
      return Math.sin(ang_radians);
   }
   static double cos_deg(double ang)
   {
      double ang_radians = deg2rad(ang);
      return Math.cos(ang_radians);
   }
   static double tan_deg(double ang)
   {
      double ang_radians = deg2rad(ang);
      return Math.tan(ang_radians);
   }


   public static void main(String[] args)
   {
      double value;

      // Notice that I don't need to create an instance
      // of MyTrig to access a static method

      value = sin_deg(30.0);
      System.out.println(" sin(30) = " + value);


      value = tan_deg(30.0);
      System.out.println(" tan(30) = " + value);

   }
}



Calling MyTrig from some other class:

If we are in some other class than MyTrig, then we need to prefix our calls with MyTrig to get at the same methods.


class SomeClass
{
   public static void main(String[] args)
   {
      double value;

      // Notice that I don't need to create an instance
      // of MyTrig to access a static method

      value = MyTrig.sin_deg(30.0);
      System.out.println(" sin(30) = " + value);


      value = MyTrig.tan_deg(30.0);
      System.out.println(" tan(30) = " + value);

   }
}




Classes

A class is a definition for a potential object. Think of a class as a skeleton or framework fthat contains the data and methods.

When a class is instantiated we then have an instance of an object.

Classes have constructors which initialize the class before it can be used.

Modifiers: (we will cover these more as the course evolves, but it is helpful to provide quick definitions)

1. "public" access modifier (optional, can be placed after final/abstract)

2. "final" modifier (optional, cannot be used with abstract)

3. "abstract" modifier (optional, cannot be used with final)

4. "class" keyword

5. name of the class

6. "extends" and the class it extends (optional)

7. "implements" and any interfaces it implements (optional)

8. curly braces {}

Example:
public abstract class MyClass extends Parent implements A,B
{
}

C++ / Java Terminology for Parent/Child Class Relationships

 | Parent Class | Child Class
C++ | Base Class | Derived Class
Java | Super Class | SubClass

A good time to do Exercise 1 and 2

If you need more practice, try the Circle Exercise

Command Line Arguments

We haven't covered Strings or Arrays yet, but it is handy to point out that we can pass in parameters into our programs as follows:




public class MainTest {
     public static void main (String [] args) {
          for (int i = 0;i < args.length;i++) {
               System.out.println("Argument " + i + ": " + args[i]);
          }
     }
}


Try out this program with the following calls:
java MainTest a b c d
java MainTest 1234 "Mary Had a Little Lamb" 5678
java MainTest

Do you understand what's going on with each of the above examples.

Modify the program to directly reference args[0], and args[1] without being in a loop. What happens when the user passes in fewer arguments that we expect. We will learn ways to deal with this later.

Constructors:

When a class is first instantiated(created), the first method to be invoked is always the constructor. Here are some constructor concepts:

- You always have a constructor. If you don't explicitly write one, the compiler creates a default one for you.
- If you explicitly create a constructor then the compiler doesn't provide you with its default constructor.
- A constructor's name is always the same as the name of the class
- Constructors don't have return values
- Constructors can't be inherited as other superclass methods are.
- The constructor method can't be final, abstract, synchronized , native or static
- When you extend a class, the constructor for the super(base) class always executes before the subclass(derived class). Try out the following example and explain its output:

//: Cartoon.java
// Constructor calls during inheritance
// Notice that the compiler automatically provides implicit calls to
// the base classes.

class Art {
  Art() {
    System.out.println("Art constructor");
  }
}

class Drawing extends Art {
  Drawing() {
    System.out.println("Drawing constructor");
  }
}

public class Cartoon extends Drawing {
  Cartoon() {
    System.out.println("Cartoon constructor");
  }
  public static void main(String[] args) {
    Cartoon x = new Cartoon();
  }
}


- But Consider the following example:

//: Chess.java
// Inheritance, constructors and arguments.
// 1.) See what happens if you comment out the explicit base constructor
//      call in the BoardGame class.  Why can't the compiler
//      automatically generate a constructor call like it did in the
//      Cartoon.java example.
// 2.) See what happens if you move the super(i) in the BoardGame to
//      after the System.out.println call.

// Comments: If you don't call a base class constructor for a derived class, the
//        compiler will attempt to call it for you.  Of course the compiler will always use
//        the default constructor which has no parameters.  Now if you don't provide any
//        constructors in your base class, the compiler will automatically generate a
//        default constructor for you.  But if you write your own constructor, the compiler
//        will not add a default constructor for you.  In this example we wrote our own
//        constructors which toke some parameter, and consequently there is no default
//        constructor.  In this case the compiler won't be able to help us with a default
//        constructor call, hence we MUST make our own base class constructor calls.

class Game {
  Game(int i) {
    System.out.println("Game constructor");
  }
}

class BoardGame extends Game {
  BoardGame(int i) {
    super(i);
    System.out.println("BoardGame constructor");

  }
}

public class Chess extends BoardGame {
  Chess() {
    super(32);
    System.out.println("Chess constructor");
  }
  public static void main(String[] args) {
    Chess x = new Chess();
  }
}




Arrays

Arrays of Primitives

Compile the following program and execute it. Read the comments to understand what is going on.


// This Example demonstrates different ways that arrays
// can be declared, uses, etc.

class ArrayTest{


// C/C++ syntax works to keep C++ people happy
static int  a1[] ;// Declares variable, but no memory allocation

public static void  main (String[] args) {
// ----------------------------------
// Completely Uninitialized arrays of ints:

    // Normal syntax
    int [] a2 =null; // Need to initialize to keep the compiler happy

    if (a1 == null) System.out.println("a1 is null now");
    if (a2 == null) System.out.println("a2 is null now");

    //  Uncomment out the following and you will get an error

    //    for (int i=0; i < a2.length; i++)
    //        System.out.println("a2(" + i + ") = " + a2[i]);


// ----------------------------------
// Initialized Arrays ints
// a3 will have 4 array elements that are initialized to zeros
// a4 will have 4 array elements with the listed values

    int[] a3 = new int[4]; // memory allocation for 4 values initialized to zero
    int[] a4 = {1, 2, 3, 4, 5, 6}; // memory allocation + initialized values

    System.out.print("a3 contains: ");
    for (int i=0; i < a3.length; i++)
        System.out.print(a3[i] + ", ");

    System.out.println("");
    System.out.print("a4 contains:" );
    for (int i=0; i < a4.length; i++)
        System.out.print(a4[i] + ", ");

    System.out.println("");

// ---------------------------------
// a7 is a 2 dimensional array filled with zeros
// a8 is a 2 dimensional array with 2 rows and 3 columns and
//           the elements contain the specified values
    int [][]a7 = new int [2][3];
    int [][]a8 = {
            {1,2,3},
            {4,5,6}
             };


    for (int i= 0; i < a8.length; i++)
        for (int j = 0; j < a8[i].length; j++)
           System.out.println("a8(" + i + "," + j + ") = " + a8[i][j]);

    }//End of main



}// End of ArrayTest Class




Arrays of Classes:


class ArrayTest2{
public static void  main (String[] args) {
//-----------------------------------
// Arrays of Classes
// A5 will reference a 3 element array of null Integer references
// A6 will be a null reference

    Integer[] A5 = new Integer[3];
    Integer[] A6;  // A6 contains null now

// ----------------------------------
// A6 and A5 now point to the same Array reference
// originally owned by A5

    A6 = A5;

    // Create some Integer classes initialized with the specified values

    A6[0] = new Integer(11);
    A6[1] = new Integer(12);
    A6[2] = new Integer(13);

    // Because A5 and A6 point to the same class reference, the following
    // will print out the class values we just created

    for (int  i= 0; i < A5.length; i++)
        System.out.println("A5(" + i + ") = " + A5[i]);

    }//End of main



}// End of ArrayTest2 Class




Exercises

1. Fill in the details to the following Rectangle class:

class Rectangle
{
   double width=1.0;
   double height=2.0;
   Rectangle()
   {
   }
   Rectangle(double height, double width)
   {
   }
   double getPerimeter()
   {
   }
   double getArea()
   {
   }
   double getAPRatio()
   {
       return getArea()/getPerimeter();
   }
   void setHeight(double h)
   {
   }
   void setWidth(double h)
   {
   }
   void print()
   {
    // Print out Width, Height, Perimeter,
    //      Area, and Area/Perimeter Ratio
   }
   public static void main (String arguments[])
   {
// Execute the following:


    Rectangle r1 = new Rectangle();
    Rectangle r2 = new Rectangle(12.0, 14.0);
    r1.setHeight(10.0);
    r2.setWidth(13.0);

    System.out.println("r1: ");
    r1.print();
    System.out.println("r2: ");
    r2.print();
   }

}


Create another class that uses the Rectangle class (fill in details on the following class). Note that as long as all of our work is in the same directory, the default characteristic is public. This will change once we start to work with packages.

class UseRectangles
{
    int num = 10;
    Rectangle[] rects = new Rectangle[num];

    public static void main (String[] args)
    {
        for (int i=0; i < num; i++)
        {
            // Call Constructor for rects[i]
            // Set Width = 2*i, and Height = 3*i
            // Print out Width, and Height
            // Print out Perimeter, Area, and Area/Perimeter Ratio
        }
    }
}


2. Add a method called getMaxSide and getMinSide to Rectangle and test out your new additions.
3. Change the above example, by making the width, height variables private. Make the default constructor private. and see what changes. Make modifications to Rectangle (i.e. add some getHeight, and getWidth routines). Modify the UseRectangles class to deal with the private variables and constructor in Rectangle.
4. Create a Class called Square which extends Rectangle. This class should have:
  - A constructor with no parameters
  - A constructor with one parameter
  - A method called setSide
  - Notice that you can use the getPerimeter, getArea, and getAPRatio as is from the Rectangle class. But you need to override setHeight, and setWidth because you want to avoid ever having a Square with a width that doesn't equal it's height.
  - Create several squares and call the print method in the Rectangle class to demonstrate that everything is working appropriately.
5. Rework the Rectangle class to be derived from the following Abstract Class called Shape that contains getAPRatio, getPerimeter, and getArea. Note that getAPRatio is implemented, but getPerimeter and getArea are only specified.


abstract class Shape
{
   Shape()
   {
   }
   abstract double getPerimeter();
   abstract double getArea();

   double getAPRatio()
   {
   	return getArea()/getPerimeter();
   }

   public static void main (String arguments[])
   {
   	Shape s = new Shape(); // This can't be executed
   }


}


6. Rework the Rectangle2 class to implement the following Shape2 Interface.


interface Shape2
{
   double getPerimeter();
   double getArea();
   double getAPRatio();
}


7. Create a Circle class similar to the Rectangle class that has the methods getPerimeter, getArea and getAPRatio. If you need a good value for PI, you can access the Math.PI constant in the Math class found in Package java.lang. Make sure you have code in your main routine to demonstrate that all of your Circle methods work.
8. Create a Circle class derived from the Abstract class Shape. In java.lang there is a static Math class with a static value of PI that you probably want to use. Make sure you have code in your main routine to demonstrate that all of your Circle methods work.
9. Create another Circle2 class the implements the Shape2 interface. Make sure you have code in your main routine to demonstrate that all of your Circle methods work.
10. Create a Polygon class similar to the Rectangle class that has the methods getPerimeter, getArea, and getAPRatio. For the getArea method just return 1000 for the area and printout a message saying its too difficult to calculate the area of a general polygon.
Consider using the following starting point for the Polygon class:


class Polygon
{
    double [] sides;
    Polygon (double[] s)
    {
        sides = s;
    }
    // Fill in other routines
}


In your main method create several instances of your Polygon class and call the Polygon methods.
11. Use your Rectangle2 (implements Shape2), Circle2(implements Shape2), and Square2(derived from Rectangle2) classes to execute the following Java class:


class UseShapes
{
    Shape2[] shapes = new Shape2[3];

    public static void main (String[] args)
    {
       UseShapes u = new UseShapes();

       u.shapes[0] = new Circle2(2.0);
       u.shapes[1] = new Square2(4.0);
       u.shapes[2] = new Rectangle2(2.0, 3.0);

       for (int i=0; i < u.shapes.length; i++)
       {
            System.out.println("Shape" + i +
                " area = " + u.shapes[i].getArea() +
                " perimeter = " + u.shapes[i].getPerimeter() +
                " A/P Ratio = " + u.shapes[i].getAPRatio());

       }
    }
}



12. Create a Triangle class that implements the Shape2 Interface. You specify triangles by 3 parameters: 2 sides and the included angle. You can figure out the length of the other side, by the law of cosines:
c^2 = a^2 + b^2 -2*a*b*cos(C)
13. Rewrite your Triangle class by moving the Law of cosines formula into a static class with a static method for the law of cosines.
14. Create a Circle3 class derived from the following Abstract class (you might have to fake a few routines):


public abstract class DrawableObject
{
   private String borderColor = "red";
   private String interiorColor ="blue";
   abstract void draw();
   public String getBorderColor()
   {
   	return borderColor;
   }
   public String getInteriorColor()
   {
   	return interiorColor;
   }
   public void setBorderColor(String c)
   {
   	borderColor = c;
   }
   public void setInteriorColor(String c)
   {
   	interiorColor = c;
   }
}


15. Create a Circle4 class that implements the following interface (you might have to fake a few routines):


interface IDrawableObject
{
   void draw();
   void distort(double distortRatio);
   void resize(double resizeRatio);
}


Last Modified: January 10, 2004 9:19 AM