Reputation: 746
recently, i read in a book about passing a user defined class as an input to scanner but it didn't explained much about the logic behind it. here's the program
import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;
class ScannerInputBase implements Readable
{
private int count;
Random rand = new Random();
ScannerInputBase(int count) { this.count = count; }
public int read(CharBuffer cb) //read is a method in Readable interface
{
if(count-- == 0)
return -1;
for(int i=0;i<2;i++)
{ cb.append('a'); }
return 1;
}
}
public class ScannerInput {
public static void main (String args[]) {
Scanner input = new Scanner(new ScannerInputBase(5));
while(input.hasNext())
{
print(input.next()+"-");
}
}
}
and it's output is
aaaaaaaaaa-
i have 2 questions here
how read() function is getting called here?
i mean i understand it's implicitly geting called somehow but from where it's getting called.
a single hyphen in the output suggests that while loop in main function is iterated only once. but why only once. i was expecting output like aa-aa-aa-aa-aa-
Upvotes: 3
Views: 2227
Reputation: 1495
how read() function is getting called here? i mean i understand it's implicitly geting called somehow but from where it's getting called.
Answer lies in the source code of Scanner
class for method next()
:
public String next() {
....
while (true) {
.....
if (needInput)
readInput();
...
}
}
Which takes us to readInput
method which is defined as follows:
private void readInput() {
......
try {
n = source.read(buf);
} catch (IOException ioe) {
.....
}
.....
}
We see that readInput
method is calling the read
method of source
object which is instance of Reader
class and is passed as an argument to the Scanner
constructor during Scanner
's object creation.
Now, Since you have passed the object of subclass of Reader
as an argument to the Scanner
constructor. And also, You have overridden the read(CharBuffer)
method witin your class, So
the overridden version of read
method is being called by the Scanner.readinput
method.
A single hyphen in the output suggests that while loop in main function is iterated only once. but why only once. I was expecting output like aa-aa-aa-aa-aa-
Because , there is no whitespace in the string aaaaaaaaaa
which is the default delimiter Pattern. Consequenty, all string is read in single iteration. So, hasNext
is returning false after first iteration and the while loop terminates.
Note: Always use
@Override
annotation while overriding a method within subclass.
Upvotes: 2
Reputation: 9741
Scanner class is a wrapper class around streams to read and write data. It has a few overloaded constructors. In your case:
public Scanner(Readable source) {
this(source, WHITESPACE_PATTERN);
}
is invoked. Because interface Readable
has only one method read(CharBuffer cb)
, ScannerInputBase
is an instaceof Readable, so the Scanner object just invokes the read() method of whatever Readable is passed.
On the second point, look at the documentation of next()
Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
The default pattern used is :
Pattern WHITESPACE_PATTERN = Pattern.compile(
"\\p{javaWhitespace}+");
SO, it your scanner's next() call, reads everything in just one go by making multiple read()
calls.
Upvotes: 0