Files and Streams

 

This chapter furthers the concepts learnt 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.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

public void init()

{

xxx a,b;

a = new xxx();

System.out.println(a.i);

b = new xxx();

System.out.println(b.i);

}

}

class xxx

{

public int i = 6;

xxx()

{

i++;

System.out.println("In Const xxx " + i);

}

}

 

C:\javaprg>appletviewer a.html

 

In Const xxx 7

7

In Const xxx 7

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:13: class xxx is public, should be declared in a file named xxx.java

public class xxx {

       ^

1 error

 

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 the constructor 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, now becomes 7. The next line, System.out.println prints the value of i as 7. Hence you see the output as

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. It may be noted that, functions or methods are shared, they don't get created again, unlike variables.

 

The next example includes the word static which precedes the variable i.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

public void init()

{

xxx a,b;

a = new xxx();

System.out.println(a.i);

b = new xxx();

System.out.println(b.i);

}

}

class xxx

{

public static int i = 6;

xxx()

{

i++;

System.out.println("In Const xxx " + i);

}

}

 

C:\javaprg>appletviewer a.html

 

In Const xxx 7

7

In Const xxx 8

8

 

With the static modifier, you will notice that a.i displays 7 and b.i displays 8. This means that i in xxx gets created only once. However, in the previous example, without 'static', if you had created 100 instances of xxx there would have been 100 i's as the variables get recreated.

 

Functions are stored in one area of memory and variables in another. Each time you say new, the functions are checked in memory. If they exists, then nothing happens. 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 or instantiate the object to access the static variable. This is shown in the next program.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

System.out.println(a.i);

}

}

class xxx

{

public static int i = 9;

}

 

C:\javaprg>appletviewer a.html

 

9

 

In this program, 'a' looks like xxx. As you can see, we have not used new anywhere. There exists a static variable i in the class xxx. System.out.println with a.i will print 9 on the screen. Here, if we make 'a' local, the compiler will return with an error saying that it has not been initialized.

 

public void init()

{

xxx a;

System.out.println(a.i);

}

 

The compiler error will be:

 

C:\javaprg>javac zzz.java

zzz.java:7: variable a might not have been initialized

System.out.println(a.i);

                   ^

1 error

 

'a' was made global earlier 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

import java.applet.*;

public class zzz extends Applet

{

public void init()

{

System.out.println(xxx.i);

}

}

class xxx

{

public static int i = 9;

}

 

C:\javaprg>appletviewer a.html

 

9

 

There is no need to declare variables in order to access static variables, the class name suffices. However to follow our regular routine, we will declare them for simplicity.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a,b;

public void init()

{

System.out.println(a.i);

b.i = 20;

System.out.println(a.i);

}

}

class xxx

{

public static int i = 9;

}

 

C:\javaprg>appletviewer a.html

 

9

20

 

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

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

a.abc();

}

}

class xxx

{

public static void abc()

{

System.out.println("hi");

}

}

 

Here a.abc calls the function abc in the class xxx. Once the function is called 'hi' is printed on the screen.

 

c:\javaprg>appletviewer a.html

 

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

import java.applet.*;

public class zzz extends Applet

{

xxx a,b;

public void init()

{

System.out.println(a.i);

b.i = 20;

System.out.println(a.i);

}

}

class xxx

{

private static int i=10;

}

 

C:\javaprg>javac zzz.java

zzz.java:7: i has private access in xxx

System.out.println(a.i);

                    ^

zzz.java:8: i has private access in xxx

b.i = 20;

 ^

zzz.java:9: i has private access in xxx

System.out.println(a.i);

                    ^

3 errors

 

The default is private, which means that only the class members can access the variable. "Outsiders are not allowed!" i.e. anyone outside the class is not allowed to access it. Try to trespass and you will definitely see the watchdog, the error.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

a=new xxx();

}

}

class xxx

{

private static int i=10;

xxx()

{

i++;

System.out.println("In Const "+i);

}

}

 

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

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public void abc()

{

}

}

class yyy extends xxx

{

public void abc()

{

}

}

 

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

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public final void abc()

{

}

}

class yyy extends xxx

{

public void abc()

{

}

}

 

C:\javaprg>javac zzz.java

zzz.java:13: abc() in yyy cannot override abc() in xxx; overridden method is final

public void abc()

            ^

1 error

 

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.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public void abc() throws IOException

{

}

}

 

C:\javaprg>javac zzz.java

zzz.java:7: cannot resolve symbol

symbol  : class IOException

location: class xxx

public void abc() throws IOException

                         ^

1 error

 

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

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

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

}

}

class xxx

{

public void abc() throws IOException

{

throw new IOException("hi");

}

}

 

C:\javaprg>appletviewer a.html

hi

 

A function can also throw exceptions and the above program demonstrates the same.

 

This program has x that looks like xxx and is created on the same line by saying new xxx(). Following this on the next line, we have 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 throw the exception. Here, it throws the predefined exception, which is IOException.

 

However before the exception is thrown, it must be created and this is possible with the help of 'new'. The constructor taking one parameter is called in this class.

 

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.

 

A couple of lines later we will show you how to create your own exceptions.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (IOException e)

{

System.out.println("In IOException "+e.getMessage());

}

catch (Exception e)

{

System.out.println("In Exception " + e.getMessage());

}

 

finally

{

System.out.println("All over");

}

}

}

class xxx

{

public void abc() throws IOException

{

throw new IOException("hi");

}

}

 

C:\javaprg>appletviewer a.html

 

In IOException hi

All over

 

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:17: exception java.io.IOException has already been caught

catch (IOException e)

^

1 error

 

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.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

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

}

}

class xxx

{

public void abc() throws ppp

{

throw new ppp("hi");

}

}

class ppp extends Exception

{

ppp(String p)

{

System.out.println("In const " + p);

}

}

C:\javaprg>appletviewer a.html

 

In const hi

null

 

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 string returned is "Sonal".

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

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

}

}

class xxx

{

public void abc() throws ppp

{

throw new ppp("hi");

}

}

class ppp extends Exception

{

ppp(String p)

{

System.out.println("In const " + p);

}

public String getMessage()

{

return "Sonal";

}

}

 

C:\javaprg>appletviewer a.html

 

In const hi

Sonal

 

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.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

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

}

}

class xxx

{

public void abc() throws ppp

{

throw new ppp("hi");

}

}

class ppp extends Exception

{

ppp(String p)

{

super(p);

System.out.println("In const " + p);

}

public String getMessage()

{

String s;

s = super.getMessage();

return s;

}

}

 

C:\javaprg>appletviewer a.html

 

In const hi

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

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

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

finally

{

System.out.println("All over");

}

}

}

class xxx

{

public void abc() throws ppp

{

throw new ppp("hi");

}

}

class ppp extends Error

{

ppp(String p)

{

super(p);

System.out.println("In const " + p);

}

public String getMessage()

{

String s;

s = super.getMessage();

System.out.println("In getmessage "+s );

return s;

}

}

 

C:\javaprg>appletviewer a.html

In const hi

All over

In getmessage hi

In getmessage hi

In getmessage hi

ppp: hi

        at xxx.abc(zzz.java:23)

        at zzz.init(zzz.java:10)

        at sun.applet.AppletPanel.run(AppletPanel.java:353)

        at java.lang.Thread.run(Thread.java:534)

 

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.

 

The reason for this fiasco is that we are not deriving ppp from Exception but instead we are deriving from Error. The error messages are to be read in the reverse order: The error is in xxx.abc, which has been called from zzz.init and AppletPanel.run calls init and so on.