Java API

Contents

 

 

Packages

 

Default package and classpath

 

Strings

 

Own packages

 

Example (Moving Average)

 

Practice exercises

Packages

Java's predefined classes are organized into packages . All of these packages together form the API (Application Programming Interface). It contains hundreds of classes for a wide variety of purposes.

The following is an overview of important packages defined in Java 1.1.

java.swing

This is the toolkit for graphical user interfaces. It contains classes for graphics output and for creating graphical user interfaces (GUIs).

java.beans

Beans technology is designed to provide ready-made elements for programming, especially graphical user interfaces. Its purpose is to enable visual programming.

java.io

Classes for inputting and outputting files, from the network, or from other sources.

java.lang

This package will be loaded automatically. It contains important things, such as the String class.

java.math

Java supports handling long numbers in this package in the form of large decimal numbers and large integers.

java.net

With this package, Java supports communication over the Internet.

java.rmi

This package contains a class that allows methods of classes on remote computers to be called over the network or by other concurrently running programs.

java.security

Since Java inherently follows a security philosophy, it supports encryption in this package.

java.text

Since Java already uses Unicode, this package offers interfaces for the development of internationalized programs.

java.util

Includes several data structures, such as growing arrays or stack storage, as well as other useful features.

Example

We will use many more examples of classes from the API later. Here, we will limit ourselves to a simple example.

import java.util.Random;

public class Test
{
    public static void main(String args[])
    {
        Random r = new Random();
        int count = 0;
        while (true)
        {
            int w = r.nextInt(6) + 1;
            count++;
            if (w == 6)
                break;
        }
        System.out.println(count + " Throws until the first 6.");
    }
}

The import command must precede the first class definition. The `Random` class is located in the `java.util` package and must be fully specified when imported. Alternatively, we can import all classes from `java.util` using...

import java.util.*;

Import. Finally, it is also possible to import nothing at all. In that case, however, the class must be specified in full.

java.util.Random r=new java.util.Random();

We use the `nextInt(n)` method of `Random`, which produces a random integer between 0 and n-1. As soon as a 6 appears, we break the loop.

Default package and CLASSPATH

In addition to the default package, every program loads the java.lang package , which the compiler locates in a predefined position. The programmer doesn't need to worry about these details, as the current directory and the directory containing java.lang are included in the normal classpath. This path can be changed by setting the environment variable CLASSPATH .

Java can also handle compressed packages. For example, in Java 1.1, all classes are packaged into a file called classes.zip. This file must also be on the classpath to be found. These are called archived classes. Such compression is particularly useful when loading over the internet. Java uses the `jar` compressor , which is written entirely in Java and creates archives with the `.jar` extension .

In DOS, the CLASSPATH is set as follows, for example.

set CLASSPATH=d:\mydir

When a Java program is compiled or executed, this path is searched for classes in addition to the normal path.

Strings

Strings are defined in java.lang . The String class has a special status in Java. For example, its own constants, namely "..." , have been introduced . Therefore, one can write

String s = "This is a string constant";

Furthermore, there is a special + operator for strings. This operator can even add strings with elementary data types, which are then converted back into strings.

String s = "Hello";
s = s + '!'; // s is now "Hello!"

Here, a char value was appended to a string. We have already concatenated double or int values ​​with strings several times in the output .

In fact, `+` can process any object that has a meaningful `toString()` method. We override the `toString()` method of objects to output the angle value.

class angle
{
    double Alpha;

    public angle(double alpha)
    {
        Alpha = alpha;
    }

    /**
     * Override the toString() method
     */
     @Override
    public String toString()
    {
        return "" + Alpha;
    }
}

public class Test
{
    static public void main(String args[])
    {
        String s = "value";
        Angle a = new Angle(Math.PI);
        s = s + a;
        System.out.println(s);
            // Prints: Value 3.141592653589793
    }
}

This example also shows how to convert a double value to a string. You simply add it to "" .

Of course, the String class also has a number of methods. It's best to consult the Java documentation for more information.

Strings can be initialized not only using `="..."` , but also via the contents of an array of `char` or ` byte` values. This is achieved using constructors. Here's an example:

public class Test
{   
    static public void main (String args[])
    {   
        char c[]={'H','a','l','l','o'};
        String s=new String(c);
            // Convert char array to string
        System.out.println(s);
    }
}

Of course, the reverse is also possible.

public class Test
{   
    static public void main (String args[])
    {   
        String s="Hello";
        char c[]=s.toCharArray(); // Convert to char array
        for (int i=0; i<c.length; i++)
            System.out.print(c[i]);
        System.out.println();
    }
}

Here, the string is output letter by letter. The string also offers methods for creating substrings and for searching.

We have already encountered strings, apart from constants, in the `args` parameter of `main` . This parameter contains an array of strings.

Here is an example that takes a word from the command line and outputs it backwards.

public class Test
{   
    static public void main (String args[])
    {   
        if (args.length==1)
        {   
            char c[]=args[0].toCharArray();
            for (int i=c.length-1; i>=0; i--)
                System.out.print(c[i]);
            System.out.println();
        }
    }
}

The program works as follows:

Java test hello
ollah

Own packages

The package in which our programs previously stored the classes was the `default` package. The classes were placed in the current directory by the compiler and found there by the interpreter.

You can also organize your own program into packages. To do this, you need to save the class files in subdirectories, but compile them from the main directory. It looks like this.

javac MyPackage/Test.java

if Test.java is a file in the MyPackage directory . Furthermore, the Test.java file must contain the command right at the beginning.

package MyPackage;

Included, i.e., before the first class definition. Thirdly, all files that want to use Test.java (except the files in MyPackage ) must import the class.

import MyPackage.Test;

or

import MyPackage.*;

This statement imports all classes in the MyPackage package . The `import` statements must precede the class definitions but follow the `package` statement. Specifically, classes from predefined packages must be imported (except from java.lang ).

Alternatively, you can address the class by its full name.

MyPackage.Test t=new MyPackage.Test();

When using the Eclipse IDE, it is sufficient to define a new class in a new project.

Example (Moving Average)

This example is numerical in nature, but perhaps also understandable and interesting for non-mathematicians. We're using a custom package here, which I 've called rene.util . Sun's naming convention requires a more specific manufacturer's name than rene , but this suffices for our purposes.

A ring buffer is a buffer whose elements we can visualize arranged in a circle. It's therefore possible to remove the bottom element or add an element to the top without moving any elements. In reality, we use an array of a fixed size. The array doesn't need to be completely filled; only a portion of it is used to store our buffer. The buffer iterates from a start index to an end index, which can be located before the start index.

As an example, let's take a buffer of length 5. We store the values ​​A, B, C, ... on the buffer one after the other. The buffer thus looks like this, step by step.

XXXXX
AXXXX
ABXXX
ABCXX
ABCDX
ABCDE

X represents unimportant array contents. At this point, the buffer is full. Now, the bottommost element must be removed to store F. This is done in two steps (pull and push).

XBCDE
FBCDE

As an example, we will now execute pull twice more. This will remove B and C.

FXCDE
FXXDE

A renewed push from G now leads, for example, to...

FGXDE

This buffer is implemented in the file rene\util\RingBuffer.java with the following code.

package rene.util;

class RingBufferOverflowException extends Exception
{
}

class RingBufferEmptyException extends Exception
{
}

/**
 * Ring buffer for storing data up to a certain size, in the style
 * first-in-first-out.
 */
public class RingBuffer
{
    private int Size, // Maximum size
            First, // First element
            Last, // Last element
            Length; // Stored elements
    private double X[];

    /**
     * Initialization.
     *
     * @param size buffer size
     */
    public RingBuffer(int size)
    {
        Size = size;
        X = new double[Size];
        clear();
    }

    /**
     * Initialization with default size.
     */
    public RingBuffer()
    {
        this(32);
    }

    /**
     * Delete.
     */
    public void clear()
    {
        Length = 0;
    }

    /**
     * Place new element on the buffer.
     *
     * @param x New value
     */
    public void push (double x) throws RingBufferOverflowException
    {
        if (Length == 0)
        {
            First = Last = 0;
            X[0] = x;
            Length = 1;
        } else if (Length < Size) // Not full
        {
            Last++;
            if (Last >= Size)
                Last = 0;
            X[Last] = x;
            Length++;
        } else
            throw new RingBufferOverflowException();
    }

    /**
     * Remove the first element of the buffer.
     *
     * @return First element
     */
    public double pull() throws RingBufferEmptyException
    {
        if (Length == 0)
            throw new RingBufferEmptyException();
        double x = X[First];
        First++;
        if (First >= Size)
            First = 0;
        Length--;
        if (First == Last)
            Length = 0;
        return x;
    }

    /**
     * Test if the buffer is empty.
     */
    public boolean isEmpty ()
    {
        return Length == 0;
    }

    /**
     * Test if the buffer is full.
     */
    public boolean isFull ()
    {
        return Length >= Size;
    }

    /**
     * @return Number of elements in the buffer.
     */
    public int length()
    {
        return Length;
    }

    /**
     * Access to elements with an index.
     *
     * @param i
     * @return Element number i
     */
    public double get (int i)
            throws RingBufferEmptyException, RingBufferOverflowException
    {
        if (Length == 0)
            throw new RingBufferEmptyException();
        if (i >= Length)
            throw new RingBufferOverflowException();
        int k = First + i;
        if (k >= Size)
            k -= Size;
        return X[k];
    }
}

This is quite extensive. First, the `package` command at the beginning ensures that the file is placed in the correct package. While it's necessary that it's located in the correct subdirectory, that's not enough.

Note that the file contains comments in a specific format. This format can be used by the Javadoc program to generate HTML pages that document the class very well. You can even use HTML code. For example, the fact that this class is not multitasking-capable is highlighted in bold.

It's interesting to see what happens when reading from an empty buffer or writing to a full buffer. In this case, we throw an exception. We use two special exceptions for this: RingBufferOverflowException and RingBufferEmptyException .

Regarding the buffer implementation, it's worth noting that in addition to the start and end indices, we also store the length. This makes it very easy to determine whether the buffer is empty or full. Managing the indices is somewhat complicated because it's necessary to constantly check whether the left side of the array is being moved.

For testing purposes, we extend the class to one that can calculate moving averages. The desired output is as follows.

1 1.0
2 1.5
3 2.0
4 3.0
5 4.0
5 4.666666666666667
5 5.0
5 5.0

The left column of numbers is predetermined. The right column is the average of the last three numbers (or less if there are fewer). For example, the average of 3, 2, and 1 is 2, the average of 5, 5, and 4 is 4.66...

Implementation is not difficult if a ring buffer is available.

package rene.util;

/**
 * A class to calculate gliding averages.
 */

public class GlidingAverage extends RingBuffer
{
    /**
     * @param size The size of the average buffer.
     */
    public GlidingAverage(int size)
    {
        super(size);
    }

   /**
     * Push an element to the sliding average buffer.
     *
     * @param x The value to be pushed
     */
    synchronized public void push (double x)
    {
        try
        {
            if (isFull())
                pull();
            super.push(x);
        } catch (Exception e)
        {
            System.out.println(e);
        }
    }

    /**
     * @return The gliding average
     */
    synchronized public double computeAverage()
    {
        try
        {
            int n = length();
            double sum = 0;
            for (int i = 0; i < n; i++)
            {
                sum += get(i);
            }
            return sum / n;
        } catch (Exception e)
        {
            System.out.println(e);
        }
        return 0;
    }
}

This class is included in the default package and is stored in the current directory (which contains the subdirectory `rene` ). Whether to keep the comments in English or German is a matter of preference.

We catch exceptions that shouldn't normally occur. This is useful for debugging the program.

The main and test programs now look like this, and are located in a different file.

public class AverageTest
{   
    public static void main (String args[])
    {   
        GlidingAverage ga=new GlidingAverage(3);
        for (int i=1; i<=5; i++)
        {   
            ga.push(i);
            System.out.println(i+" "+ga.computeAverage());
        }
        for (int i=0; i<3; i++)
        {   
            ga.push(5);
            System.out.println(5+" "+ga.computeAverage());
        }
    }
}

We store the numbers 1 to 5, then the number 5 three more times, and print the average of the last three numbers each time. The output is shown above.

Exercisetasks

  1. Refer to the documentation for the BitSet class. Write a prime number sieve for the prime numbers up to 1,000,000. To do this, initialize all bits to true and then remove the multiples of all numbers (set the corresponding bit to false) that have not yet been removed (the prime numbers). Count the prime numbers up to 1,000,000 in this way.
  2. Make the sieve from step 1 more effective by only removing the necessary multiples and only setting bits for odd numbers.
  3. Write a subroutine that tests whether a string is a palindrome (a word that sounds the same forwards and backwards). Use the `charAt()` method of `String` for this .
  4. Refer to the documentation for the StringBuffer class, which represents a dynamically growing string. Write a program that removes each occurrence of double letters from a string by copying the string into a dynamically growing string buffer.

Solution .

Problems without solutions

  1. Use the Vector class to store the first 100,000 prime numbers.
  2. Write a program that extracts the part between the two parentheses ( and ) from a string , or the empty string "" if these parentheses do not appear in the string. If you use the `indexOf()` method of ` String` , be sure to consider special cases such as "a)(avc)" .
  3. Write 2. by creating a char array of the string.
  4. Write a subroutine that reverses a string. Use a char array or the StringBuffer (but not its reverse() method !).

Back to the Java course