• Post Reply Bookmark Topic Watch Topic
  • New Topic

How to validate Scanner input which was passed in a previous(calling) method  RSS feed

 
Mark Richardson
Ranch Hand
Posts: 108
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have 3 classes in my mini program in which I am trying to learn the return statement. The problem I am experiencing is somewhere in my Processor class, where my Scanner input which has been taken in the InputTaker class doesn't appear to be honored. What am I doing incorrectly?

Launcher:



InputTaker:



Processor:



actual souce code for download: https://www.dropbox.com/s/citoctp0qm791kc/returnstatement.zip?dl=0
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are facing the same problem as with your other topic...

https://coderanch.com/t/682059/java/java-util-NoSuchElementException-received-input

Never, ever, close a scanner instance, when it is wrapped on a stream that you did not open. In this case, you wrapped standard input, you close the scanner which closed standard input, and can no longer access standard input.


Also, you are doing a reference comparison, of user input with a string literal. Since user input is always instantiated, the comparison will always report that the references are different... consider using the equals() method instead.

Henry
 
Mark Richardson
Ranch Hand
Posts: 108
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:You are facing the same problem as with your other topic...

https://coderanch.com/t/682059/java/java-util-NoSuchElementException-received-input

Never, ever, close a scanner instance, when it is wrapped on a stream that you did not open. In this case, you wrapped standard input, you close the scanner which closed standard input, and can no longer access standard input.


Also, you are doing a reference comparison, of user input with a string literal. Since user input is always instantiated, the comparison will always report that the references are different... consider using the equals() method instead.

Henry


Ok, I just removed the scannerObject.close(); in my InputTaker.java class - However, this is giving me the same exact result. Nothing happens if I enter Tokyo, and nothing happens if I enter something other than Tokyo...
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Richardson wrote:Ok, I just removed the scannerObject.close(); in my InputTaker.java class - However, this is giving me the same exact result. Nothing happens if I enter Tokyo, and nothing happens if I enter something other than Tokyo...


Please re-read this part of my response again...

Henry Wong wrote:
Also, you are doing a reference comparison, of user input with a string literal. Since user input is always instantiated, the comparison will always report that the references are different... consider using the equals() method instead.


Henry
 
Mark Richardson
Ranch Hand
Posts: 108
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:
Mark Richardson wrote:Ok, I just removed the scannerObject.close(); in my InputTaker.java class - However, this is giving me the same exact result. Nothing happens if I enter Tokyo, and nothing happens if I enter something other than Tokyo...


Please re-read this part of my response again...

Henry Wong wrote:
Also, you are doing a reference comparison, of user input with a string literal. Since user input is always instantiated, the comparison will always report that the references are different... consider using the equals() method instead.


Henry


Ah, thank you!  I did this and it worked. Is there somehow I can improve this even further?  For example, if I wanted to add an "ignore case" so that both tokyo and TOKYO would work. How would I approach that?


 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Richardson wrote:For example, if I wanted to add an "ignore case" so that both tokyo and TOKYO would work. How would I approach that?


Did you try the equalsIgnoreCase() method?

Henry
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't like that input class, I am afraid.
  • 1: You usually only need one instance of Scanner reading from System.in. The way to get one instance only is to declare it static.
  • 2: That means all your methods will have to be static, too.
  • 3: That means you never need any instances of the input class, so look in the Java® Language Specification to find out how you prevent a class from being instantiated.
  • 4: You have now created a utility class, so call it Inputs rather than Input. (Or similar.)
  • 5: Never close that Scanner. Once you have closed it you can't reopen System.in, and that is that.
  • 6: Avoid nextLine() if possible partially because there is a potential pitfall with it and partially because methods like nextInt and nextBigDecimal are so much more useful.
  • Now try creating an Inputs class. Remember you can keep that class for ever and use it again and again, enhancing it as necessary.

    And yes, you have seen me tell you to make things static.
     
    Mark Richardson
    Ranch Hand
    Posts: 108
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:I don't like that input class, I am afraid.
  • 1: You usually only need one instance of Scanner reading from System.in. The way to get one instance only is to declare it static.
  • 2: That means all your methods will have to be static, too.
  • 3: That means you never need any instances of the input class, so look in the Java® Language Specification to find out how you prevent a class from being instantiated.
  • 4: You have now created a utility class, so call it Inputs rather than Input. (Or similar.)
  • 5: Never close that Scanner. Once you have closed it you can't reopen System.in, and that is that.
  • 6: Avoid nextLine() if possible partially because there is a potential pitfall with it and partially because methods like nextInt and nextBigDecimal are so much more useful.
  • Now try creating an Inputs class. Remember you can keep that class for ever and use it again and again, enhancing it as necessary.

    And yes, you have seen me tell you to make things static.


    Thank you for your wonderful points! If I am to understand everything correctly:

    points 1-5:

    Am I to create a fourth class in my program and call it Inputs.java, and this will be my reusable utility class? or did you mean to scrap my InputTaker.java class entirely and replace it with the new Inputs.java?

    I've created a 4th class called Inputs.java, as shown below, which has a private constructor, as you suggested, but I'm not sure what to do with my globalScannerObj as I can't really use a dot operator on it to use its members...




    point 6: Since in this particular class "Tokyo" is a String, I assumed that .next() was the way to go, as opposed to .nextInt()  correct? or no?
     
    Campbell Ritchie
    Marshal
    Posts: 56570
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That's a good start. Make the Scanner field private (and probably final too) however. As it is, any code in the same package can reassign that Scanner object or access it to do something naughty, like closing it.

    Of course you can use the dot operator, in lots of places. Where you may find you have given it too long a name. The simplest is this:-There are better ways to write that method. Much better, even to the extent that it becomes robust to incorrect inputs, but try that in the first instance. You will of course have to scour the Scanner documentation to work out what to write instead of xxxxx. Now you have got that class, you can use it forever to get an int from the keyboard. As I said, search my posts for utility class Scanner and see what you find. We also have an FAQ somewhere about the same subject: look in our Wiki forum.
     
    Knute Snortum
    Sheriff
    Posts: 4281
    127
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    6: Avoid nextLine() if possible...

    I've written two "input data from the console" type classes, and the above statement is the kicker.  I found that if you completely avoid nextLine() then you can never (or I don't know how to) write a method like this:

    ...or this
     
    Mark Richardson
    Ranch Hand
    Posts: 108
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:That's a good start. Make the Scanner field private (and probably final too) however. As it is, any code in the same package can reassign that Scanner object or access it to do something naughty, like closing it.

    Of course you can use the dot operator, in lots of places. Where you may find you have given it too long a name. The simplest is this:-There are better ways to write that method. Much better, even to the extent that it becomes robust to incorrect inputs, but try that in the first instance. You will of course have to scour the Scanner documentation to work out what to write instead of xxxxx. Now you have got that class, you can use it forever to get an int from the keyboard. As I said, search my posts for utility class Scanner and see what you find. We also have an FAQ somewhere about the same subject: look in our Wiki forum.


    I've been searching using Google and CodeRanch's search facilities for "Utility Class Scanner" since yesterday, but the results I come up with show me you referring to this fabled utility class, but I can't seem to locate the actual thing

    Went through these posts, for example:


    https://www.coderanch.com/forums/jforum?module=search&action=search&forum_id=1&search_keywords=campbell+ritchie+utility+class+scanner&match_type=all&search_in=ALL&forum=&groupByTopic=true&sort_by=time&sort_dir=DESC&search_date=ALL&member_number=&member_first_name=&member_last_name=&member_match_type=memberPosted
     
    Knute Snortum
    Sheriff
    Posts: 4281
    127
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Try this search:

    https://www.coderanch.com/forums/jforum?module=search&action=search&forum_id=1&search_keywords=scanner+utility&match_type=all&search_in=ALL&forum=33&forum=1&groupByTopic=true&sort_by=time&sort_dir=DESC&search_date=ALL&member_number=&member_first_name=Campbell&member_last_name=Ritche&member_match_type=memberPosted

    (search for "scanner utility", member name first "Campbell", last "Ritche", forums [hold down Ctrl key and select] Beginning Java, Java in General)
     
    Campbell Ritchie
    Marshal
    Posts: 56570
    172
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Try the 8th hit on that search, replying to Nick Woodward, and the two links in that post.
    Try the 13th‑14th hits on that search, replying to Winston Gutkowski, but you may have to look a long way down the thread before you strike oil.
    Try the 15th hit on that search, replying to Chan Ag, but go through the whole thread and beware of where I might have made a mistake.
    Try the 21st‑22nd hits on that search, replying to Jordan Wiliams.
    I think those will be the most helpful posts. You will in probably find out lots more by reading the whole thread.
    See whether my counting is miles out.


     
    Mark Richardson
    Ranch Hand
    Posts: 108
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:Try the 8th hit on that search, replying to Nick Woodward, and the two links in that post.
    Try the 13th‑14th hits on that search, replying to Winston Gutkowski, but you may have to look a long way down the thread before you strike oil.
    Try the 15th hit on that search, replying to Chan Ag, but go through the whole thread and beware of where I might have made a mistake.
    Try the 21st‑22nd hits on that search, replying to Jordan Wiliams.
    I think those will be the most helpful posts. You will in probably find out lots more by reading the whole thread.
    See whether my counting is miles out.


    Mr. Ritchie, I'm a little embarrassed, but I wasn't able to locate the relevant posts. (Also, were you referring to Knute's search or the one I posted?) In either searches, I got a little overloaded with the information and wasn't sure which was relevant. If you can please pin-point me to what this utility class looks like   Thank you.
    Staff note (Liutauras Vilda):

    Fixed quote

     
    Campbell Ritchie
    Marshal
    Posts: 56570
    172
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It was in your search. Maybe I counted the posts wrongly. Try 1 2 (appears twice in your search) 3 4 and 5.
    The links might be to posts or the threads containing those posts, and you may need to read a long way. I made a serious mistake in one post, which you will have to look hard for.
     
    Liutauras Vilda
    Sheriff
    Posts: 4923
    334
    BSD
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    @OP

    Don't you want to write a validator for your input?

    InputTaker is responsible for taking an input, logically, validator class supposed to be able to validate an input, so somebody else would know, if they can proceed with it or no.

    There can be strings validator, so it would check length, some other stuff you may need.
    There could be numbers validator: integers, floats/doubles...
    There could be date validator...

    What do you think?
     
    Mark Richardson
    Ranch Hand
    Posts: 108
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Liutauras Vilda wrote:@OP

    Don't you want to write a validator for your input?

    InputTaker is responsible for taking an input, logically, validator class supposed to be able to validate an input, so somebody else would know, if they can proceed with it or no.

    There can be strings validator, so it would check length, some other stuff you may need.
    There could be numbers validator: integers, floats/doubles...
    There could be date validator...

    What do you think?


    Oh wow. That is an excellent real-world consideration! Let me start thinking about it and see how far I get!


     
    Liutauras Vilda
    Sheriff
    Posts: 4923
    334
    BSD
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    More to think towards.

    1. Create an interface Validator (or similar), have one method in it, validate(think about parameters list).
    2. Create specific validators classes which implements Validator interface.
    3. Create generic validator which picks up needed validator on the fly (you'll need factory method for that)
    4. Create factory class to give you a specific singular implementation.

    It is quite easy. Do some research. All classes will be very small. No 2 classes will be as big as many validation aspects you'll have.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!