3

This question is purely academical (I am getting into Java coming from a C# background).

I am wondering how could I extend the java.util.Scanner class to add a Scanner.nextChar() method.

(Please note that the answer may not be specific to Scanner.nextChar(), but just about the general steps to extend a native class. Much appreciated.)

  • 1
    At least for the specific case, you don't. If you really need to read one character at a time, use something like a `BufferedReader` instead. – Dennis Meng Oct 13 '13 at 00:21
  • 1
    You could read a String with Scanner.read() and break the string into chars with the split methods: Scanner.read().toCharArray(). This may not be what you are looking for, but it could give the same result. – TAAPSogeking Oct 13 '13 at 00:55
  • 1
    Scanner isn't a native class, in the Java sense. – user207421 Oct 13 '13 at 03:01

3 Answers3

3

Scanner is a final class, you cannot extend it. If it would be a non-final class, you can just extend it. As Dennis suggested, you can use the BufferedReader#Read method to read a single char.

Perhaps extend Reader and simulate a BufferedReader?

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
2

Since Scanner is final you cannot declare a subclass of it. Period.

  • Reflection won't work / help.
  • Byte engineering tricks won't work / help.

Conceivably, you could modify the Scanner class to remove the final modifier. However, the fact that this is class is in one of the reserved packages means that you would need to modify the Java installation to make this happen. (You might also be able to do it by modifying the bootclasspath ... but that amounts to the same thing.)

But to be honest, if is not really necessary to modify Scanner. Instead, you could simply copy the Scanner source code (e.g. from the OpenJDK codebase) and use it to create an "unrelated" class in your application's package space that has the extra method. It won't by type-wise related to the real Scanner class, but that is unlikely to be a concern.


For the record:

  • This Q&A - https://stackoverflow.com/a/18746676/139985 - provides some possible reasons why Scanner does not support readChar. (Noting of course that it is clearly "opinion".)

  • The most likely reason for making Scanner final is security. A final Scanner class means that a Scanner instance can be safely passed from non-trusted code to trusted code in a sandboxed environment.

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

To emulate nextChar you can try using next with empty delimiter.

Scanner s = new Scanner("a\nb\tcd\re");
Pattern original = s.delimiter();// in case you wnat to get back to
                                // default delimiter

s.useDelimiter("");

while (s.hasNext()) {
    char c = s.next().charAt(0);
    System.out.println("'" + c + "'");
}

result

'a'
'      (here is printed value of `\n`) 
'
'b'
'   '  (here is printed value of `\t`) 
'c'
'd'
'      (here is printed value of `\r`) 
'
'e'
Pshemo
  • 122,468
  • 25
  • 185
  • 269