Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Technical Tips

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
Print Button
 
Tech Tips index

Tech Tips
August 11, 1998

This issue presents tips, techniques, and sample code for the following topics:

Filter Streams
If you've read much about the Java programming language, you may have encountered filter streams. A stream refers to an ordered sequence of bytes or other data, with a source (for input streams) or a destination (for output streams). Streams are used for file I/O, networking, pipes, and so forth.

A filter stream is two or more streams hooked together to provide added functionality. For example, one stream may provide a method to read in a large block of characters efficiently, while another stream built on the first one could offer a mechanism for buffering those characters so they can be read one at a time in an efficient way. Another example of filtering would be support for tracking line numbers.

To see how all this works, consider the following program that searches a text file for a pattern, and displays each line containing the pattern along with its line number:

import java.io.*;
  
  public class filter {
    public static void main(String args[])
    {
      if (args.length != 2) {
        System.err.println("usage: pattern file");
        System.exit(1);
      }
      String patt = args[0];
      String file = args[1];
  
      try {
        FileReader fr =
          new FileReader(file);
        LineNumberReader lr =
          new LineNumberReader(fr);
        String str;
        while ((str = lr.readLine()) != null) {
          if (str.indexOf(patt) != -1) {
            int ln = lr.getLineNumber();
            System.out.println(file + "["
              + ln + "]: " + str);
          }
        }
        lr.close();
      }
      catch (IOException e) {
        System.err.println(e);
      }
    }
  }

The example uses the LineNumberReader class in preference to the older LineNumberInputStream that has been deprecated.

LineNumberReader is a buffered input reader that tracks line numbers as it goes. In other words, successive large chunks of the file are read into a buffer using FileReader. FileReader is a class that sets up a FileInputStream based on an actual file, and then uses the mechanisms of its superclass InputStreamReader to convert a stream of bytes into a sequence of Java language characters. readLine is then called to read each line in turn from the buffer. When a line terminator is detected, an internal line number counter is incremented, and its current value is retrieved using getLineNumber.

Note that you can also design your own filter streams. One example is to extend java.io.BufferedReader so that readLine skips blank lines and returns only the lines that contain non-whitespace characters.

Default Constructors
Suppose that you have a superclass and a subclass as follows:

  class A {
    A() {/* ... */}
  }

  class B extends A {/* ... */}

and you create a new instance of B by saying:

  B bref = new B();

B defines no constructors, but B is extended from A, and A does have a constructor that needs to be invoked for the instance of B. How does this work?

What happens is that a default constructor is generated automatically, and the constructor calls the superclass constructor with no arguments. So "new B()" results in the generated default constructor for B being called, and it in turn calls the no-argument constructor for A. The generated constructor is given the access modifier "public" if the class is public, or else the constructor is given the default access implied by no modifier.

You can actually observe a default constructor in generated code. For example, for the following source code:

class A {}

the result of "javap -c" (see Tech Tips: Jan 20, 1998), is:

  Method A()
     0 aload_0
     1 invokespecial #3 <Method java.lang.Object()>
     4 return

In other words, a constructor for A is generated, and it simply invokes the superclass (in this case java.lang.Object) constructor.

Relying on default constructor generation is not necessarily good coding practice. In such a case it might be worth inserting an explanatory comment. Note also that you can control class instantiation by means of protected or private constructors. For example, a class used only as a packaging vehicle for class methods and variables might define a private constructor, making it uninstantiable.


Print Button
[ This page was updated: 21-Sep-2000 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary | Feedback | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-2000 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.