Introduction Now that we have laid the groundwork for developing servlets, let's get back to the basics. This chapter carries on from where we left off in the first two chapters. It details a few more features of the Java Programming language. Let's understand the first program in this chapter, where we have two
simple classes. In Const xxx 7 You can have as many classes as you like in a file, but only one of them can be declared public. You will get an error if you make more than one class public. Add public to the xxx class as well and it will display an error as shown below. C:\javaprg>javac zzz.java zzz.java:14: Public class xxx must be defined in a file called "xxx.java". In this program, class zzz is declared as public but class xxx is not.
a and b are two objects that look like xxx. Let us remind you that here
you do not call the constructor; it is called by new at the time the object
is created. The next line is, a=new xxx(). In the constructor, i, which
has the value 6, will now become 7. The next line, System.out.println
prints the value of i as 7. Hence you see the output as C:\javaprg>appletviewer a.html In Const xxx 7 The statement b=new xxx() creates one more variable named i. This is because new creates the variables again. a.i and b.i will both have the same value. A point to be noted here is that the functions don't get created again. Functions can be shared but not variables. The next example includes the word static which precedes the variable i. zzz.java C:\javaprg>appletviewer a.html In Const xxx 7
Functions are stored in one area of memory and variables in another. Each time you say new, it checks to see if the function exists in memory. If it exists, then the function isn't added. In other words, functions are loaded into memory only once, but the variables within the class are created afresh each time. An object is an instance of a class and when a class is instantiated, the variables are created afresh. i as a variable is now related to the object and not to the class. Whereas static variables have nothing to do with the object, they go with the class. You don't have to say new to access the static variable. This is shown in the next program. zzz.java C:\javaprg>appletviewer a.html 9 public void init() The compiler error will be: C:\javaprg>javac zzz.java zzz.java:9: Variable a may not have been initialized. 'a' was made global so it does not have to be initialized. a.i displays 9, which means that there is one and only one i. We repeat, static variables can be accessed without creating the object. Here's another example to prove the same point zzz.java C:\javaprg>appletviewer a.html 9 At first a.i will print 9. Then b.i is initialized to 20. b.i and a.i are the same because i is a static variable and is shared. So when you say a.i again, the value of i is 20. As you can see, you don't have to create an object to use static variables. The next program introduces the concept of a static function that returns void. zzz.java Here a.abc calls the function abc in the class xxx. Once the function
is called 'hi' is printed on the screen. hi The need for static functions will be discussed a little later in this chapter. In the following program, the static variable 'i' is declared to be private. zzz.java C:\javaprg>javac zzz.java zzz.java C:\javaprg>appletviewer a.html In Const 11 Here xxx increments the value of i by saying i++ and display its value. Only the constructors and functions in xxx have access to i. The variables 'a' and 'b', though created in zzz and in the very same file, are not allowed to access i. zzz.java In the above program, apart from zzz there are two more classes, xxx and yyy. Class xxx has a function called abc. Class yyy extends xxx and also has a function named abc. This will not result in any compilation errors. The next program introduces a small change. Here the word 'final' precedes
void abc(). zzz.java:13: The method void abc() declared in class yyy cannot override
the final method of the same signature declared in class xxx. Final methods
cannot be overridden. Final methods cannot be changed or overrriden. Since abc has been made final, the class yyy cannot have another function abc. The abc in xxx is final, thus you can't change it. It is not without purpose that such a concept has been introduced in Java. Let's understand the rationale behind it. Let us assume that you have your own class with a final function. Others will derive from it, but if they want to override the same function, they will not be allowed to do so. They will get the error shown above. Without the use of final there is no guarantee that the function will not be overridden. Thus to prevent the overriding of a function, it must be made final. Now, in xxx, we are creating a function named abc. C:\javaprg>javac zzz.java zzz.java:7: Class IOException not found in throws. The function abc throws an exception, or to be more specific, it throws IOException. The full name is java.io.IOException, hence we need to import java.io.* zzz.java C:\javaprg>appletviewer a.html hi A function takes parameters and along with it, it can also throw exceptions. This tells us more about the function. This program has x that looks like xxx and is created on the same line by saying new xxx(). This does not give us any problems at all. The next line has x.abc(), where we call this function. abc returns a void and throws an IOException. Within the curly braces, the command 'throw' is used to actually throw the exception. Here, it throws the predefined exception, which is IOException. Before the exception is thrown, it must be created. It is created with the help of 'new'. We are calling the constructor, which takes one parameter, in this class. A couple of lines later we will show you how to create your own exceptions. Every exception thrown must be caught, so catch catches Exception, which is the base class for all exceptions. System.out.println prints the return value of e.getMessage. e looks like Exception and the getMessage function in e displays "hi". "hi" is displayed because this is what was given in the constructor. You can have as many catches as you want for the different exceptions you want to catch. zzz.java finally C:\javaprg>appletviewer a.html In IOException hi Here's one more example where we catch IOException and then Exception e. Since abc throws an IOException, the IOException will be called and not the second one. Once the first catch is executed, the execution of the other catches stops. Reversing the catch order will generate an error. C:\javaprg>javac zzz.java zzz.java:13: catch not reached. In the try and catch, we have introduced a new word 'finally'. The code in the curly braces, which has been given after the word 'finally' is called when everything is over. Hence you see 'All over'. 'finally' gets called irrespective of the throws. To check this, comment out the throw and you will still see 'All over'. 'finally' is used to execute code at the end of 'try' and 'catch' pair. It can be used to close a file that was opened in the program. The file will be closed irrespective of whether the exception takes place or not. Ready for something interesting? We are now going to show you how to
create your own exception. In const hi Here we are calling our exception ppp which extends Exception, the base class of all exceptions. Then we create a constructor, which accepts one parameter 'p'. This value is displayed using System.out.println. There you go! Exception created. When we say x.abc, at first abc in xxx gets called and it immediately throws an exception. This will call the constructor in ppp. The p in the constructor has the value 'hi', hence we see 'In const hi'. But e.getMessage does not return any value, so we see null. Since we do not have the getMessage function, the one in Exception is called and it returns a null. In our next program, we have added the getMessage function in ppp and the statement returned is "Sonal". zzz.java C:\javaprg>appletviewer a.html In const hi To print the value returned by e.getMessage, our getMessage will be called and thus you see 'Sonal'. This is not the correct way to go about doing things, so we now set it in the right way. When we create an object, our constructor is given 'hi' as a parameter. This constructor should call the original constructor and give it the same string. Then, the getMessage function in our code should receive the value returned by the original function, which will be the value to be returned back. The next program implements these two things. C:\javaprg>appletviewer a.html In const hi In ppp, we have super(p) which must be written on the very first line. It is used to call code in the original. By original we mean the class that we have derived from. In our case, the constructor in Exception will be called with one parameter p. This constructor stores the string. In getMessage, we again have super.getMessage. super.getMessage will call getMessage from the base class, which is Exception. The getMessage returns a string, which is stored in the variable s and then we simply return s. Now the program will work in the required manner. Our next example is slightly larger. zzz.java C:\javaprg>appletviewer a.html In const hi Class zzz has a variable x as an object that looks like xxx. The statement,
x.abc, calls the function abc which throws an exception called ppp. The
constructor gets called, hence 'In const hi' is displayed. This is the
first line of output. Then 'finally' gets called because of which 'All
over' is displayed. The catch code will be the next to be called and because
we have System.out.println, it will constantly print e.getMessage, which
contains 'hi'. Once all this is over, it will tell you that there was
an error int xxx.abc at zzz.init. Building 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. In fact, the HotJava browser is just a Java application. qqq.java 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 >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 we want our code 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 just a little later. 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 that any executable can do. In the next program, we have added a function named main. qqq.java 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 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. main 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, you cannot mess with it. First you must say public
or private, then static and then give the return value. Compile it and
then say java qqq. It will display 'hi'. hi Now let's print out a[0] and a[1]. qqq.java 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 Say java qqq one at the command prompt, this will first show one on the screen and then give the same error. C:\javaprg>java qqq one one To eliminate the error, say java qqq one two. C:\javaprg>java qqq one two one 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 because the array is limited to only one member. 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 C:\javaprg>java qqq one C:\javaprg>java qqq one two three In Java, an array class has a member called length. If you say java qqq one, a.length will be 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]. This is how, depending on the parameters passed, all the members of the array can be displayed. Now, let's try writting data to the disk. In this program, fos is an object that looks like FileOutputStream. We know how much 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. qqq.java 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 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 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 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 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 You can't be satisfied with just this, can you? So let's write an entire object to a file in one stroke.
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
C:\javaprg>java qqq Let's see how arrays can be saved to the disk. qqq.java 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 C:\javaprg>java qqq hi 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 C:\javaprg>java qqq a1 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 C:\javaprg>java qqq a1 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 C:\javaprg>java qqq 1 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 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.
C:\javaprg>java qqq 2 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. 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 As previously, 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 C:\javaprg>java qqq abc 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 readig this hapter, we
hope you are now well versed with the concept of multidimensional arrays
in connection with objects and classes.
|