Solved

System.in.read()

Posted on 2002-04-01
12
377 Views
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?

0
Comment
Question by:motorway
  • 4
  • 3
  • 2
  • +3
12 Comments
 

Expert Comment

by:rashidkamranbs
Comment Utility
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
0
 

Expert Comment

by:0xDEADBEEF
Comment Utility
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
http://java.sun.com/j2se/1.4/docs/api/java/io/InputStream.html
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.
0
 

Expert Comment

by:0xDEADBEEF
Comment Utility
Err... of course Random is instanciated like  

private Random rnd = new Random();

Too much C++ stuff lately...
0
 

Author Comment

by:motorway
Comment Utility
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.
0
 

Expert Comment

by:rashidkamranbs
Comment Utility
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();
in.read();

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 :-)
0
 

Author Comment

by:motorway
Comment Utility
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.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 16

Expert Comment

by:imladris
Comment Utility
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.
0
 

Expert Comment

by:rashidkamranbs
Comment Utility
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
0
 

Author Comment

by:motorway
Comment Utility
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?
0
 
LVL 19

Expert Comment

by:Jim Cakalic
Comment Utility
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:
    System.out.println(System.in.getClass().getName());

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:
    http://www.artima.com/underthehood/invocation.html

Best regards,
Jim Cakalic
0
 

Accepted Solution

by:
rashidkamranbs earned 50 total points
Comment Utility
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 :)
0
 
LVL 9

Expert Comment

by:Venci75
Comment Utility
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.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Venci75
EE Cleanup Volunteer
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

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 This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

771 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

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now