Building Java Applications

 

So far you have been building Applets, now let's build Applications.

 

Applets and applications are very similar in appearance, with one key difference: A Java application is an independent piece of software; an applet is not. The applet is loaded and run by a browser or viewer.

 

qqq.java

public class qqq

{

}

 

Start by saying public class qqq { }. Here, no import statements are used. When you run the program by saying javac, you get a file named qqq.class and no errors. To see the application work, instead of appletviewer, run another program called java.

 

C:\javaprg>java qqq

Exception in thread "main" java.lang.NoSuchMethodError: main

 

This program gives an error saying that you don't have a function called main.

 

At times, you may get a different error that looks like the statement given below

 

Exception in thread "main" java.lang.NoClassDefFoundError: qqq

 

Then you must set the classpath to the current directory. In order to do so give the command

 

>set CLASSPATH=.;%CLASSPATH%

 

So far we have been using Java as a programming language. We have written code that executes in a browser. Whenever code runs in a browser, it is called an applet.

 

This time however we want our program to run as a standalone application. To do so, we require a program called java, also known as the Java Virtual Machine. We will go in depth into the differences between an applet and an application in a short while. As of now, it is important to understand that a Java applet can't read and write to a file on disk, whereas a Java application can do anything, similar to an executable.

 

In the next program, we have added a function named main.

 

qqq.java

public class qqq

{

public static void main(String a[])

{

System.out.println("Hi ");

}

}

 

Earlier, in this chapter, we discussed static variables and static functions where we explained that we don't have to create an object to access them. main here is a static function and it takes an array of strings named a. You may choose to name the array as you please. main has been declared public, otherwise, it won't be visible or accessible. This function has also been made static so that it is available to Java without creating the object that looks like qqq. Static functions are always available irrespective of you using new or not. main returns void because it is not returning anything here.

 

The order is important, dare not mess with it. First comes public or private, then static and then give the return value. Compile it and then say java qqq. It will display 'hi'.

 

C:\javaprg>java qqq

hi

 

Now let's print out a[0] and a[1].

 

qqq.java

public class qqq

{

public static void main(String a[])

{

System.out.println(a[0]);

System.out.println(a[1]);

}

}

 

Run the compiler and then say java qqq. It will give an error saying, ArrayIndexOutOfBoundsException.

 

C:\javaprg>java qqq

 

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

at qqq.main(qqq.java:5)

 

Give the command as  java qqq one at the prompt; this will first show one on the screen and then give the same error.

 

C:\javaprg>java qqq one

 

one

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

at qqq.main(qqq.java:6)

 

To eliminate the error, say java qqq one two.

 

C:\javaprg>java qqq one two

 

one

two

 

Simply saying java qqq does not create an array of strings because no parameters have been given after qqq. java qqq one will create only one element in the array because only one argument is specified. Hence printing the second member will give an error. The last command that you tried, java qqq one two, creates two elements and since you are displaying two members you see no errors.

 

Elements in the array are created with respect to the parameters specified. What we are trying to say here is that if you go beyond the bounds of the array, an exception will be generated.

 

The next program is a generic one, which displays all the command line arguments without showing any errors.

 

qqq.java

public class qqq

{

public static void main(String a[])

{

int i;

for ( i = 0 ; i < a.length ; i++)

System.out.println(a[i]);

}

}

 

C:\javaprg>java qqq one

one

 

C:\javaprg>java qqq one two three

one

two

three

 

In Java, an array class has a member called length. When you give java qqq one, a.length is 1 because there is only one member. java qqq one two three will make a.length 3 as there are three members. Since the condition is i< a.length, the value of i will start from 0 and keep changing till it is less than 3 i.e. 2. System.out.println will therefore print a[0] ,a[1], a[2].

 

In this manner, depending on the parameters passed, all the members of the array can be displayed.

 

Now, let's try writting data to the disk.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

}

catch (Exception e){e.getMessage();}

}

}

 

In this program, fos is an object that looks like FileOutputStream. We know shortcuts are appreciated, so to avoid writing the full name the import statement has been used. To create a new instance FileOutputStream requires one parameter, the name of the file. Our subdirectory is c:\javaprg and the file name we want to use is z.ser. Similarly, make sure you give the complete path to the constructor.

 

fos is now an object that looks like FileOutputStream. The name FileOutputStream itself suggests that the file will be in output mode, i.e. we can write to the file. Stop here, compile the file and run it. You will find that z.ser is created in the subdirectory but it's size is 0 bytes.

 

Now to write to this file.

To do that, another object is needed that looks like ObjectOutputStream. This class takes the FileOutputStream variable as a parameter and so we pass fos to it. This stream is closed on the next line.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

Compile this program and run it. A directory listing in the javaprg subdirectory will display the file size as 4 bytes.

 

The bytes are shown in dec, char and hex below.

 

172 ac

237 í ed

0 0

5 - 5

 

Now we will actually write to this file.You may wish to write strings and many more things to the file. oos is used to write to fos, fos stands for z.ser. In the program below, we are simply writing AB.

 

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject("AB");

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

Check the size of the file. It is a very small file and the size is 9 bytes. You can also see 2, which is the length of the string and then AB.

 

172 ac

237 í ed

0 0

5 - 5

116 t 74

0 0

2 2

65 A 41

66 B 42

 

In the program below, we are writing two strings to the file. One string is AB and the other is CDE. The output is shown below.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject("AB");

oos.writeObject("CDE");

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

You will notice that the string always starts with 116, followed by 0. After that, we have the length of the string and then the string itself.

 

172 ac

237 í ed

0 0

5 - 5

116 t 74

0 0

2 2

65 A 41

66 B 42

116 t 74

0 0

3 3

67 C 43

68 D 44

69 E 45

 

You can't be satisfied with just this, can you? So let's write an entire object to a file in one stroke.

 

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

xxx x;

x = new xxx();

try

{

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(x);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

class xxx implements Serializable

{

public int i=6;

String s = "hi";

}

 

In the above program, x is an object that looks like xxx. It has two members - int i and String s. writeObject with x will write the entire object to the file.

 

Class xxx implements Serializable. This is an interface but it does not have any functions. So,it is assumed that it only has variables. ObjectOutputStream is used to take the entire object and write it to disk in one stroke.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

xxx x;

FileInputStream fos = new FileInputStream("c:\\javaprg\\z.ser");

ObjectInputStream oos = new ObjectInputStream(fos);

x = ( xxx ) oos.readObject();

System.out.println(x.i);

System.out.println(x.s);

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

class xxx implements Serializable

{

public int i=60;

String s = "Byes";

}

 

 

Instead of FileOutputStream and ObjectOutputStream, the above program uses FileInputStream and ObjectInputStream. In the previous example, we had writeObject and here we have readObject. We have to cast it to xxx. Now when you print x.i and x.n, the value will be that of the earlier program, it doesn't take the new values.

 

C:\javaprg>java qqq

6

hi

 

Let's see how arrays can be saved to the disk.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

String a[];

a = new String[2];

a[0] = "hi";

a[1] = "Nono";

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

The concept of arrays has already been explained. Here 'a', an array of strings, is created. a[0] is initialized to 'hi' and a[1] to 'Nono'. Using writeObject, the entire array is written to disk. 'a' has the length of the array so it knows how much to write.

 

Thinking of taking a break? Great idea! But please do so after trying out the next program. The next program will read from the same file into an array. So you need to try this right now.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

String a[];

FileInputStream fos = new FileInputStream("c:\\javaprg\\z.ser");

ObjectInputStream oos = new ObjectInputStream(fos);

a = (String [] ) oos.readObject();

System.out.println(a[0]);

System.out.println(a[1]);

System.out.println(a.length);

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

hi

Nono

2

 

First run the earlier program where you wrote the array to the disk and then the current one. In this program, readobject will read from the file. Whatever is read in is assigned to a. Since we have cast the output to an array of strings, 'a' now contains the data as Strings. Therefore, it displays 'hi' and 'Nono' and the length is displayed as 2.

 

Multi-Dimensional Arrays

 

Let's understand multidimensional arrays. In Java, there is no such thing as a multidimensional array. Arrays are limited to one dimension. But what if you need more complex data structures such as two or three dimensions? For this you can fake multidimensional structures by building arrays within arrays.

 

qqq.java

public class qqq

{

public static void main(String argv[])

{

String a[][] = {{ "a1","a2","a3"} , { "b1","b2","b3"} };

int i;

for ( i = 0 ; i<a.length ; i++)

{

System.out.println(a[i][0]);

}

}

}

 

C:\javaprg>java qqq

 

a1

b1

 

In order to create multidimensional arrays use two square brackets. In this program, the multidimensional array is of strings, so it is declared as string a [ ] [ ]. At the same time, the array is also being initialized using curly braces. Since there are two sets of curly brackets, we can say that we have an array a[2],[3]. Each one of them is an array and each one has 3 members.

 

The for loop starts by initializing i to 0. a.length will give you 2 because the array only has two members, each one of them in turn is an array, so their length should be three. When we say println a[i][0], it is a[0][0]. This will print the first member of the first array, that is, a1. When i becomes 1 we are printing a[1][0] and this will print b1.

 

The next program enables you to print all the members in the array.

 

qqq.java

public class qqq

{

public static void main(String argv[])

{

String a[][] = {{ "a1","a2","a3"} , { "b1","b2","b3"} };

int i,j;

for ( i = 0 ; i<a.length ; i++)

{

System.out.println(a[i][0]);

for ( j = 0 ; j < a[i].length ; j++)

{

System.out.println(a[i][j]);

}

}

}

}

 

C:\javaprg>java qqq

 

a1

a1

a2

a3

b1

b1

b2

b3

 

The objective here is to print all the members in the array. i in the for loop is initialized to 0; the condition is i<a.length. a.length will give 2. So the println will print the value in a[0][0], which is a1. Then we have another for loop within the earlier for. j in the loop gets initialized to 0; the condition is j < a[i].length. The length here will be 3 because the first array has 3 members. Remember, a[0] and a[1] are both arrays. So j will be 0,1,2 and thus will print all members of the array.

 

The same is applicable to ints also. The following program demonstrates this.

 

qqq.java

public class qqq

{

public static void main(String argv[])

{

int [][] m;

m = new int[3][];

int i;int k = 1;

for ( i = 0 ; i < m.length ; i++)

{

m[i] = new int[2];

m[i][0] = k++;

m[i][1] = k++;

}

for ( i = 0; i < m.length ; i++)

{

System.out.println(m[i][0]);

System.out.println(m[i][1]);

System.out.println("-");

}

}

}

 

C:\javaprg>java qqq

 

1

2

-

3

4

-

5

6

-

 

Here, the variable has been created in a slightly different manner. You can create it either by saying int m[ ] [ ] or int [ ][ ]m. The square brackets can be put before or after the variable, it's just a question of syntax. They both mean the same thing. m=new int[3][ ] will create 3 arrays but how many members each of them will hold is not known. It has been left blank for the moment. Then we have a for statement where m.length will be 3 because there are 3 arrays, so the for will go on three times.

 

In the for, we say m[i] = new int[2]. This is how we initialize these arrays. Since i is 0, the 0th member of the array will hold two values. m[i][0] is actually m[0][0], which we are initializing to the value of k. k as of now is 0 which is the value given to m[0][0]. k++ will increment the value by 1, so k becomes 1. This is given to m[0][1]. When the bracket is reached, i will be incremented by 1, so it becomes 1. m[1] is now an array which will have 2 elements. And m[i][0] is now m[1][0] which refers to the second array and the 0 th element in the array. Since k has not been initialized again, k will retain its original value and will keep incrementing.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

String a[][] = {

{ "a1","a2","a3" },{ "b1","b2","b3" }};

//a = new String[3][2];

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

oos.close();

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

In this program, the multidimensional array has 2 arrays each with 3 members. It could have been created as shown in the comment and we could have initialized every member later. It really doesn't make any difference. With writeObject, the entire object will be written to disk.

 

The next program reads from the file and prints it in the form of an array.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

String a[][];int i,j;

FileInputStream fos = new FileInputStream("c:\\javaprg\\z.ser");

ObjectInputStream oos = new ObjectInputStream(fos);

a = (String [][] ) oos.readObject();

System.out.println(a.length);

for ( i = 0 ; i < a.length ; i++)

{

for ( j = 0 ; j < a[i].length ; j++)

System.out.println(a[i][j]);

}

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

2

a1

a2

a3

b1

b2

b3

 

Here, we want to read all the strings, so we read the object into a. The for statement initializes i to 0 and it keeps incrementing i till it is less than the length, which is 2. This for will go on twice, the second for is the one that prints a1, a2, a3 in the first round and b1, b2, b3 in the second round.

See how easy it is to write and read an array of strings. Let's see if we can work with chars as comfortably.

 

The difference between an array of chars and an array of strings is that a char holds a single entity whereas a string holds multiple entities.

 

The following program has a multidimensional array with 2 arrays each 3 members large. The values given are 'a' 'b' 'c' 'd' 'e' 'f'.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

char a[][] = {

{ 'a','b','c' },{ 'd','e','f' }};

FileOutputStream fos = new FileOutputStream("c:\\javaprg\\z.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

oos.close();

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

As before, we are writing the object in one stroke to the file and in a similar way we are reading it from the file.

 

qqq.java

import java.io.*;

public class qqq

{

public static void main(String argv[])

{

try

{

char a[][];

FileInputStream fos = new FileInputStream("c:\\javaprg\\z.ser");

ObjectInputStream oos = new ObjectInputStream(fos);

a = (char [][] ) oos.readObject();

System.out.println(a[0]);

System.out.println(a[0][0]);

System.out.println(a[1]);

}

catch (Exception e){System.out.println("bye");e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

abc

a

def

 

a[0] within the println prints all the characters in one stroke. To print individual characters we have to be specific, like a[0][0] is 'a' and so on. a[0] will print the entire string 'abc' and a[1] will print out the entire string 'def'.

 

Thus the crux is that using ObjectInputStream and ObjectOutputStream you can read and write arrays to the disk.

 

Conclusion

 

In this chapter, you learnt about static variables and static functions and gained some insight into the concept of constructors.We also showed you how you can create your own exceptions.

 

Apart from the applets that you have been creating, you are now able to create applications. Using ObjectInputStream and ObjectOutputStream you can read and write arrays to the disk. After reading this chapter, we hope you are now well versed with the concept of multidimensional arrays in connection with objects and classes.