Posted on 2002-04-01
Medium Priority
Last Modified: 2010-03-31
System.in returns and object of InputStream which is an abstract class and read() is an abstract method of this class. Then how does this work, since we need to implement this read in some subclass. How does this work?

Question by:motorway
  • 4
  • 3
  • 2
  • +3

Expert Comment

ID: 6911040
Well well .. ya missed something very imporatnt.. let me tell ya how this happen the magic in OOP.. See.. when we design a class hierarchy.. what we do we place general behaviour in the top level calsses most of the time interfaces or abstract calsses the purpose is to create a common interface for all the classes belongs to or we place rite inthe bottom with concrete implementation..

Now what happen in this casee.. the Object assigns to InputStream .. which is System.in is actually an object of a class that completely implements the read method.. but cuz it extends the InputStream it is an input stream.. n can be assigned to the reference of type InputStream..

a possible impl could be..

InputStream in=new InputStream(){
  int read(){
    //do read here

What i want to show ya is the thing that Abstract Classes and intefaces just make contracts and concrete classes have to full fill the contract by providing implementation.. what about Name.. doesn't matter as i used Anonymous..  n yes.. late binding .. or what we call overriding.. is the key :-) hope i m clear.. sorry for being too long

Expert Comment

ID: 6912390
That depends on what you want to do.
Usually one of the classes derived from InputStream that come with the JDK work wuite well. Browse
for more information on them. If these don't work for you, you'll have to write your own class. In case you want to use this  class on more than one occasion, you want to name it, like:

class myInputStream extends InputStream {
  //override methods here

In case you use it only once, you may want use an anonymous class, like rashidkamranbs mentioned. This looks like

BufferedInputStream myStream = new BufferedInputStream(new InputStream(){
     //TODO: Stuff
     private Random rnd();

     public int read(){
       return rnd.nextInt();

Hope this helps.

Expert Comment

ID: 6912392
Err... of course Random is instanciated like  

private Random rnd = new Random();

Too much C++ stuff lately...

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.


Author Comment

ID: 6912629
Thanx rashidkamranbsm, but i have one query.
There are many subclasses derived from inputstream implementing read() method. How does the interpreter come to know which version of read() to call.

Expert Comment

ID: 6912641
Well this is something we call Late Binding.. (by the way in java all the function bindings are late)

At compile time compiler just verifies if the method exist or not.. and at run time the actual method is called..

Lemme give you an example

suppose you write a class

class MyInputStream extends InputStream{
   public void read(){
     //my read impl

now suppose you write a line of code like
InputStream in=new MyInputStream();

The compiler checks if read() exisit int inputstream or not cuz reference type is inputstream but at rum time from the actual object that is of type MyInputStream the actual method is called.. thats late binding.. n always calls the correct copy. isn't awesome :-)

Author Comment

ID: 6912733
But in System.in.read(), System.in refers to an input stream and InputStream has many classes derived from it implmenenting read(). How would it know of which derived class read() should be called. The example you have given
InputStream in=new MyInputStream();
atleast we know it is of type MyInputStream.
But System.in doesn't tell which InputStream to refer. e.g. ObjectInputStream or some other derived class implementing this read() method.
LVL 16

Expert Comment

ID: 6913123
It doesn't differentiate based on the source code perse. System.in is a reference to a specific object. Each object contains information about its type and methods. The "late binding" is achieved by the object containing enough information to make it possible that the read of "this" object gets executed.

Expert Comment

ID: 6913625
What i just try to depict from the sample code is

1. A reference is important for compiler compiler verifies the function call rite from the reference type.. (correct me if i m not)

2. At run time.. the reference type is forgotten n object is asked to run the method.. n belive me object in its nature is supposed to be a complete entity.. n it contains everything that could be called from the very reference of the object..

so when InputStream's reference cotains MyInputStream stream the read is called from that object..

if it cotains datainputstream .. the read is called from that stream.. n conventionally every calss that ends with InputStream is supposed to be a sub class if InputStream

Author Comment

ID: 6914639
Following is are the derived classes of InputStream each overriding the read() method.
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream

Now System.in.read() will the call the method of which derived class?
LVL 19

Expert Comment

by:Jim Cakalic
ID: 6915865
As the previous posts indicate, the key to understanding this is to understand inheritance. Inheritance hierarchies permit concrete objects in the hierarchy with specialized behavior to  be substituted for each other at run time as necessary. There are, in fact, numerous implementations of java.io.InputStream with implementations specific to the source of the data being streamed -- AudioInputStream, ByteArrayInputStream, FileInputStream, StringBufferInputStream, etc. Depending on the source of the input, the correct class is chosen (directly by your application or some other mechanism), and an object constructed to provide access to that data source. From that point forward, due to the common inheritance of each of these classes from InputStream, the rest of your application need not care about the specific source of the data. Your reliance is upon the methods defined by InputStream even though the specific implementation of those methods is in one of the subclasses.

In the case of System.in, it is declared to be no more specific than InputStream because the native platform hosting the JVM may impose varying requirements on which subclass could actually be used. Most of the time, it is likely that this will be a BufferedInputStream wrapping a FileInputStream on a native FileDescriptor. But that doesn't have to be the case. Be assured that when you reference System.in, you are actually referencing some subclass of InputStream. But which one doesn't really matter. In fact, you can find out _which_ subclass is used this way:

This is likely to return BufferedInputStream. This will probably wrap a FileInputStream which references a FileDescriptor passed by the native OS. This is definitely how it works in my installation. In fact, looking at the source for the System class, it initializes 'in' as:
    new BufferedInputStream(new FileInputStream(FileDescriptor.in));

FileDescriptor.in is a static reference to the standard input stream provided to the JVM by the OS. (Remember that the JVM is a C/C++ native implementation so it shouldn't be too suprising that it gets file descriptors for stdin, stdout, and stderr just like any other C/C++ application.)

Just a clarification that not _everything_ is done using dynamic (aka late) binding. The JVM actually has 4 different instructions for invoking methods. The compiler chooses which instruction to issue at compile time.

invokestatic -- All static method invocation is done using this intruction. It is a form of "early" or static binding. The method the JVM invokes is based on the type of the object reference which is always known at compile-time.

invokevirtual -- This is the real workhorse of polymorphic invokation. The method to invoke is based on the actual class of the object, which may only be known at run time. This is definitely "late" or dynamic binding.

invokespecial -- Sometimes dynamic binding would not yield correct results so the compiler chooses to use invokespecial to force static binding in 3 situations: 1) when calling the compiler-synthesized <init> method during object construction, 2) when calling private methods, and 3) when calling superclass methods directly using the super keyword.

invokeinterface -- Method invokation through an interface requires some special handling because the JVM cannot make as many assumptions about its own internal structures as when dealing directly with classes. This is essential invokevirtual with an extra level of indirection (and overhead).

In summary, class (static) methods are _always_ statically bound (at compile time) whereas instance methods are dynamically bound except in the case of <init> methods, private methods, and methods invoked through super.

If you'd like to know more, here's a link to a great article explaining method invokation:

Best regards,
Jim Cakalic

Accepted Solution

rashidkamranbs earned 200 total points
ID: 6915913
Here is Your Question motorway
Following is are the derived classes of InputStream each overriding the read() method.
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream,
PipedInputStream, SequenceInputStream, StringBufferInputStream

Now System.in.read() will the call the method of which derived class?

Ya just need to concentrate on Inheritance.. read() would be called from the object you instatiate by using new
if its new ByteArrayInputStream() .. read fromt that object..
or if its XXXInputStream the read() from XXiputStream.. cuz if you write something with new.. mean the class is concrete.. n thats gives you 100% surity that it implements read..

i think this should be finished now :)

Expert Comment

ID: 7932501
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
Answered by: rashidkamranbs
Please leave any comments here within the next seven days.
EE Cleanup Volunteer

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Suggested Courses
Course of the Month16 days, 3 hours left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question