...
Create and use only a single BufferedInputStream
on System.in
. This compliant solution declares the BufferedInputStream
as a class variable so that all methods can access it. However, if a program were to use this library in conjunction with other input from a user that needs another buffered wrapper on System.in
, the library must be modified so that all code uses the same buffered wrapper instead of additional ones that are created.
Code Block | ||
---|---|---|
| ||
public final class InputLibrary { private static BufferedInputStream in = new BufferedInputStream(System.in); public static char getChar() throws EOFException { int input = in.read(); if (input == -1) { throw new EOFException(); } in.skip(1); // This statement is now necessary to go to the next line // The noncompliant code example deceptively worked without it return (char)input; } public static void main(String[] args) { try { System.out.print("Enter first initial: "); char first = getChar(); System.out.println("Your first initial is " + first); System.out.print("Enter last initial: "); char last = getChar(); System.out.println("Your last initial is " + last); } catch(EOFException e) { System.out.println("ERROR"); } } } |
...
This program was compiled with the command javac InputLibrary.java
on a system with Java 1.6.0. When run from the command line with java InputLibrary
, the program successfully takes two characters as input and prints them out. Also, when run with java InputLibrary < input
, where input
is a file that contains the exact same input, the program successfully takes two characters as input and print them out.
Compliant Solution
If a program intends to use the library InputLibrary
in conjunction with other code that requires user input and consequently needs another buffered wrapper around System.in
, its code must use the same buffered wrapper as the one used by the library, instead of creating and using an additional buffered wrapper. The library InputLibrary
must return an instance of the buffered wrapper to support this functionality.
Code Block | ||
---|---|---|
| ||
public final class InputLibrary {
private static BufferedInputStream in = new BufferedInputStream(System.in);
// Other methods
static BufferedInputStream getBufferedWrapper() {
return in;
}
}
// Some code that requires user input from System.in
class AppCode {
private static BufferedInputStream in;
AppCode() {
in = InputLibrary.getBufferedWrapper();
}
// Other methods
}
|
Note that this scheme may not work very well in multi-threaded environments because by default, reading from a stream is not a thread-safe operation. Explicit synchronization is required in such cases.
Risk Assessment
Creating multiple buffered wrappers around an InputStream
can cause unexpected program behavior when the InputStream
is re-directed.
...