• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Rob Spoor
  • Devaka Cooray
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • Jj Roberts
  • Al Hobbs
  • Piet Souris

Looping Questions

 
Ranch Hand
Posts: 52
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Right now when I'm trying to loop questions in any of my programs each one is surrounded by a while loop until it is answered correctly. The problem is when there are multiple questions it gets very repetitive to have each one surrounded by a while loop. having them all in one while loop repeats all the questions which i dont want. Is there any simpler way to repeat the individual questions that were answered incorrectly?
 
Marshal
Posts: 26909
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, sure there is. When you find yourself writing repetitive code like that, the first idea you should have is to write a method which encapsulates the frequently-repeated code. Try that and see how far you get with it?
 
Saloon Keeper
Posts: 8704
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I provided this example to someone else the other day, you may find it useful. I tend to create a number of small methods that are specific to a data type (e.g. int) but not the question. Written correctly they can be highly reusable. They can also include input validation and looping so that it doesn't  clutter the main body of your project.
 
Gurtej Grewal
Ranch Hand
Posts: 52
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks, I haven't used encapsulation a lot so I definitely need to get more familiarized with it. Just looking at your code I remembered a question I've had but never really asked. Using the Static keyword isnt the best thing for OOP (from what ive heard) and I see youve used it with the Scanner. Is there a reason for this? What ive usually done is set the scanner in the main method and passed it as a parameter to any method that required it.
 
Carey Brown
Saloon Keeper
Posts: 8704
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Scanner is "static" and "final", meaning it is a constant which is why the variable is in all-caps; SCAN. The reason for this is that there should only Ever be one Scanner made from System.in - in your entire project ! So, no closing, no re-opening, and as a constant no need to pass it around.

You'll also not the prompt method is static because it should be totally independent of any class instance data unless it's passed in as a parameter.

Over time you can begin to collect these in a utility class which has only static members. In my signature below there's a link to my KeyboadUtility class which  has lots of other examples.

You'll also note that I use SCAN.nextLine() instead of one of the more data type specific Scanner methods, this forces all inputs to be concluded by pressing enter and leaves no dangling data in the keyboard input buffer.
 
Saloon Keeper
Posts: 13366
295
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Personally I think this is not a good pattern to emulate.

Yes, it's true that you should only ever wrap one buffered I/O object around System.in, but making a static field out of it is NOT a good idea.

Static fields should only ever be used for real constant values, or for cross-cutting services such as loggers. Using them for business logic services hides dependencies and makes your application harder to test and debug.

You really MUST pass the scanner into all methods and constructors that need it. While this may seem messy to you, it really is not as bad as it sounds, and it will result in code that clearly indicates which parts require I/O.
 
Marshal
Posts: 74341
334
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I suppose it is possible to have multiple Scanners reading System.in, but I agree it is a bad idea and can lead to confusion as to which input is read where. Also, remember that Scanners are not thread‑safe; the simplest answer to this problem is that when you move to a multi‑threaded program, you restrict keyboard input to one thread and one thread only.
I prefer to keep the Scanner as private static final, and use it only via static methods in my utility class. That obviates the risk of anybody accessing the Scanner and doing something like changing the delimiter while nobody else is watching I don't pass my Scanner to methods in other classes. I don't pass my Scanner full stop.
 
Stephan van Hulst
Saloon Keeper
Posts: 13366
295
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So why are you worried about somebody changing the delimiter when nobody is watching, but not worried about somebody consuming input using your utility class when nobody is watching?
 
Carey Brown
Saloon Keeper
Posts: 8704
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Personally I think this is not a good pattern to emulate.

Yes, it's true that you should only ever wrap one buffered I/O object around System.in, but making a static field out of it is NOT a good idea.

Static fields should only ever be used for real constant values, or for cross-cutting services such as loggers. Using them for business logic services hides dependencies and makes your application harder to test and debug.

You really MUST pass the scanner into all methods and constructors that need it. While this may seem messy to you, it really is not as bad as it sounds, and it will result in code that clearly indicates which parts require I/O.

They ARE clearly indicated because they only reside inside the KeyboadInputs utility class.

Do you not consider STDIN a constant?
 
Campbell Ritchie
Marshal
Posts: 74341
334
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:. . . not worried about somebody consuming input using your utility class . . .

How could you avoid that? If anybody writes new Scanner(System.in) anywhere, you are up the creek without a paddle anyway.
 
Stephan van Hulst
Saloon Keeper
Posts: 13366
295
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:They ARE clearly indicated because they only reside inside the KeyboadInputs utility class.


Yes, but you won't be able to tell that your code is using the KeyboardInputs class just by looking at method signatures. This can lead code maintainers to make wrong assumptions about code they didn't write, and make it difficult to test and easy to introduce new bugs.

Even if you're writing code just for yourself, and you think passing services to constructors/methods is onerous, I don't think it's a good thing to teach this to beginners.

Do you not consider STDIN a constant?


No. Standard input produces different results upon different method calls. By definition, it is not constant. Assigning non-value types to globally accessible variables is one of the biggest contributors to buggy spaghetti code.

Campbell Ritchie wrote:How could you avoid that? If anybody writes new Scanner(System.in) anywhere, you are up the creek without a paddle anyway.


Yes, and it's a shame that the Java designers chose to make standard input available through a static field, instead of an application context injected into the main method. But is that a good argument for adding even more static references to non-value types to your application? You're just adding different ways for your application to access standard input unexpectedly.

Can either of you tell me why you think this is so terrible?
 
Carey Brown
Saloon Keeper
Posts: 8704
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In the  CONTEXT of putting together a textual user  interface for a project it has worked well for me to gather and isolate all dependence on System.in inside a utility class. I have found, in practice, that this has made my project code much cleaner and less prone to the pitfalls of multiple System.in calls being spread around. Is it perfect? No. Does it work for me? Absolutely.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic