Win a copy of Rust Web Development this week in the Other Languages forum!
  • 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:
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Junilu Lacar
  • Rob Spoor
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Tim Moores
  • Jesse Silverman
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Piet Souris
  • Frits Walraven

IOException

 
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

In this program I have to capture an input of the user and then print out the name in the array of the integer position that was given. However, if the position is out of range I need to capture the error and print out a simple error message. I am getting an error with the catch (IOException e) line. Gives me a bunch of syntax errors as such:
Syntax error on token "catch", ( expected
Syntax error, insert "-> LambdaBody" to complete LambdaExpression
Syntax error, insert "AssignmentOperator Expression" to complete Assignment
Syntax error, insert ";" to complete Statement
 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A catch clause is part of a try/catch statement:


Your code only has the catch part.
 
Marshal
Posts: 74632
335
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
. . . and why are you using IOException at all? I don't think that code is likely to throw that sort of exception in the first place. If you pass a non‑existent array index (e.g. −1), you will suffer a different sort of exception. I think you are better writing a loop (or at least an if‑else) testing whether your number is in the required range than throwing exceptions.
Also I suggest you change the instruction in line 9, so it tells you what sort of number is required.
 
Bartender
Posts: 2900
150
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A bit more info about the program above...
One of Scanner's constructor does throw an IOException (this one), but the constructor you are using (see here) does not throw that exception:
Next, if you want to handle the out of range issue, you can look out for the ones thrown by in.nextInt(). According to Javadocs (see here)

Javadocs wrote:public int nextInt()
Scans the next token of the input as an int.
An invocation of this method of the form nextInt() behaves in exactly the same way as the invocation nextInt(radix), where radix is the default radix of this scanner.

Returns:
the int scanned from the input
Throws:

  • InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
  • NoSuchElementException - if input is exhausted
  • IllegalStateException - if this scanner is closed
  • you can do this:Learn to read the javadocs for all constructors and methods that you are using and you would be good !
     
    Campbell Ritchie
    Marshal
    Posts: 74632
    335
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I think the problem is that somebody might enter an int with the wrong value for an array index. I think it is possible to deal with that sort of problem with an if‑else and not use any exceptions at all.
     
    Rancher
    Posts: 144
    9
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    When you try to access a wrong index a IndexOutOfBoundsException is thrown, wich is a sub-class of RuntimeException.
    My opinion about such RuntimeException is: Most exceptions have ways to check them properly before access. So, anything that's avoidable and still throws an Exception is the fault of the programmer.

    Example:

    If I want to access files, I have to make sure if it exists, if I can read it, and if I have to if I can write to it. This way I can at least prevent IOExceptions thrown by OS-level "not found" or "access denied". The reason an IOException could be thrown in this scenario would be if some technical issue occurs while reading/writing the file - like hardware drive crash.

    To the topic:

    First, I wouldn't rely on Scanner as it's error prone when used incorrectly. Scanner.nextInt() screams for errors as normal command line appends a new line. So, Scanner takes the int but the new line is still in the buffer as no next() is called.
    I would use Scanner.nextLine() and then Integer.parseInt(). I wouldn't use Scanner at all but rather Integer.parseInt(BufferdReader(InputStreamReader(System.in)).readLine()).
    Next, I would build a loop catching any non valid input and print error message. If input is valid, then a range check follows. If and only if all checks go green then I would return the element. So this way I would avoid exceptions all togehter.

    Anyway. I guess there're several possibilities how to do it, maybe there's even a "best" or "right" way. But, unless it gets the job done, it doesn't matter how it's done. Some is poor style, some is good. We all just can give input based on our personal knowledge and prefernce.
     
    Campbell Ritchie
    Marshal
    Posts: 74632
    335
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    KH, that's a good post

    Kristina Hansen wrote:. . .  Scanner . . . error prone when used incorrectly. . . . .

    All forms of keyboard input are similarly error‑prone. You will have similar problems if you use Integer.parseInt(). As Winston Gutkowski pointed out a long time ago, the problem with Scanner for keyboard input is that it is poorly documented, and many books confidently tell readers that Scanner#nextLine() returns the next line.

    . . . I would build a loop catching any non valid input and print error message. If input is valid, then a range check follows. If and only if all checks go green then I would return the element. So this way I would avoid exceptions all togehter. . . . .

    That is exactly what I do. Rob Spoor taught me how to write a loop allowing me to avoid exceptions from a Scanner:-Line 7 is needed to remove the incorrect input; otherwise that is an opportunity for an infinite loop (‍). Lines 6 and 7 can go in either order. Readers may be able to think of a better error message for line 6.
    As long as you don't do anything daft like feeding ctrl‑D or ctrl‑Z to the keyboard, that loop will run without exceptions and reliably return the next valid int. Note that I wrote that as a method; I have a utility class called resources.KeyboardInputs. The remainder of the class follows the usual conventions for utility classes. Yes, I can request values in a certain range, but I throw an illegal argument exception rather than suffer another infinite loop if the wrong values for max and min are entered.That class takes account of how a Scanner works, and makes full use of its parsing abilities, and minimises the possibilities for throwing exceptions anywhere. Remember that a Scanner consumes most of the exceptions it encounters but most BufferedReader methods declare throws IOException, which means you need boilerplate try‑catches. Somebody tested code here once, and concluded that a buffered reader reads faster than a Scanner, but who is going to worry about a few μs for parsing when it takes several seconds to write the input with the keyboard.
    I have overloaded my methods and have methods for next(...) and nextLine() which never return an empty String. But I am keeping quiet about their details at the moment.

    It would be possible to add an if‑else to the OP's (original poster's) code to display an error message if the input is out of the correct range for indices for that array, and as I said earlier, the OP may be able to dispense with exception handling completely.
     
    Kristina Hansen
    Rancher
    Posts: 144
    9
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Campbell Ritchie I'm with you. May let me explain why I see Scanner 'more' error prone:

    In addition to your already mentioned poor documentation lots of beginners just don't understand it well and therefor wrongly uses it (wich leads to the many threads we all know here).
    Most I see the issue that the inner workings about how input from some command prompt gets into the call of Scanner.next().
    Many beginners think this way:
    I want to read an integer. When I type a number in the console this goes to the code. FIN
    What they don't know about:
    Most consoles (either OS terminals or IDE ones) read "lines" wich include a line terminator ((\r)\n) wich gets sends along as input. So, when nextInt is called, the line termination is still in the buffer as it's not processed yet, but as no next() or nextLine() is called to clear it, on the following call to nextInt() gets wrong as it now tries to process the line terminator to a number - wich fails.
    I don't know if for this issue the poor documentation is to bleam, bad design of the Scanner class, or the way how use of Scanner is tought (either in class or in books) - but that's the main issue in my eyes. The book I learned Java from (around 15 years ago) was written back for 1.4.2 (the previous book was even older and was for 1.3) - so Scanner wasn't a think back then (according to doc it was added in 1.5 (5.0 as it was advertised by the installer)). They this book tought me to read input was this:

    To my shame, that's how I still use it today.
    But also, the book explained the details how input works very broadly. So it explained the difference between platforms (back then, Mac used only \r (Is this still a thing?)), wired quirks for then popular IDEs (IIRC either Netbeans or Eclipse had a very bad implementation of its console back then wich caused all wired issues not able to reproduce on "normal" terminal) and also the "unix way" of chain tools together with pipe output of one into input of next and how to handle this. So, I very deeply learned the way Java reads input from System.in and writes output to System.out/.err - and in my eyes this basic knowledge, wich for me is important to know and understand, got less and less important over the past 10 years. I have to admit, it made me start to roll my eyes when I see all this topics by beginners wonder why Scanner doesn't work as they expect because they use it "wrong" (or maybe better: not in the right way) - wich I blame the lack of the above mentioned input/output low-level basics.
    So, Scanner wouldn't be so bad if it would been tought correctly and the documentation gets cleaned up to reflect the lack of such basics (although, back when it was written these basics where commonly known so it was to be expected an experienced developer understands how to use Scanner and that nextInt() only returns the number but not the line terminator added by the console).
    Today, with Java 13, there maybe way better methods to read and process data I'm not yet aware of (I'm still learning how to use streams and functional programming). But many sources just throw beginners into cold water.

    To may get a bit off-top here to the discussion about why many not so familiar with streams: For the last ten years ways Java is taught didn't changed to reflect how Java has changed. It's still the same: procedual Hello World all in main, then object oriented. Not much teachers or books already fit for then either make the jump to functional or start teach it from the beginning (although overall concept of object oriented is needed to understand how Java works).
    So, unless the way how Java is taught doesn't reflect Javas changes, wich might will take another 10 years, it wont change how Java is used in development. But that's just my personal view about this situation.
    To admit: I never fully got into NIO network or NIO.2 file programming. I'm aware it exists and that it's very powerful as it uses underlying modern OS features wich in turn helps to boost performance, but there was no project yet I had to use them. Same goes for jigsaw: I know there is some modularization but neither did I understood it nor needed to use it.

    Anyway, back to topic:

    The basic question of OP was about illegal code catch without try, wich then drifted to an argue about use exceptions vs perform checks (or in term of PHP: user input sanitization). To wrap this up: There're several ways, some considered better than others mostly by personal preference, and a few good "common practice". I guess there's even a functional way to do it wich I'm not aware of. What and how OP uses depends on his personal choice.

    Kris
     
    Campbell Ritchie
    Marshal
    Posts: 74632
    335
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Kristina Hansen wrote:Campbell Ritchie I'm with you. . . . a line terminator ((\r)\n) . . . when nextInt is called, the line termination is still in the buffer as it's not processed yet, but as no next() or nextLine() is called to clear it, on the following call to nextInt() gets wrong as it now tries to process the line terminator to a number - wich fails. . . ..

    I haven't had that problem with Scanner. The default delimiter is whitespace, and that includes line ends, so you can writeor...and both ints will be recognised by calls to nextInt(). There is a problem with nextLine(); the documentation clearly says it returns the remainder of the current line, so if you have read to the end of the line, nextLine() will return an empty String and subsequent calls to anything appear to be out of sequence. I learnt ways to correct that problem soon enough, which many people don't seem to do

    . . . around 15 years ago . . .

    About the same time I started learning Java┬«. If you find the 2005 edition of Core Java II by Cay Horstmann and Gary Cornell (vol I page 738) it suggests changing a Scanner to option pane to produce code compatible with Java 1.4. So Horstmann would have used option pane for keyboard input before Java5.

    . . . Mac used only \r

    It has since changed to be a Unix‑like system using \n.

    . . . Scanner wouldn't be so bad if it would been tought correctly and the documentation gets cleaned up  . . .

    Exactly. If you are going to call a method nextLine(), users will think it reads the next line.quote]Today, with Java 13, there maybe way better methods to read and process data . . .If you mean keyboard input, I don't think there are. There are methods for buffered readers and Scanners to create Streams directly. As before,, a buffered reader reads one line at a time and a Scanner reads one token at a time. They work differently. You can summate all the ints from the keyboard stopping with the first 0 like this:-I haven&apospt got the time to eplain that code more fully.

    . . .  many not so familiar with streams: For the last ten years ways Java is taught didn't changed to reflect how Java has changed. . . .

    Fortunately people were taught Streams where I am, but your complaint is only too true in many places. There are now many books teaching up to date Java®, too including one by Cay Horstmann.

    Hope to see you again soon
     
    Kristina Hansen
    Rancher
    Posts: 144
    9
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Campbell Ritchie
    The main issue is, that most beginners have loops look like this:

    So, there is just no call to Scanner.next() or .nextLine() hence the line terminator is still unprocessd in the buffer wich then causes the next call to nextInt() to fail as the line terminator can't be parsed to a number.
    It's not about next() just takes the line terminator and nextLine() returns an empty string as it's never called.

    Reason (in my eyes): Most beginners just don't know (or don't understand) that when one has a terminal, enters a number and hits return, that not just the number (or correct: the characters entered) sent to Java but a terminal also appends a line terminator, so they write codes wich doesn't handle this extra data. What most beginners think happens when you hit enter is that just the number is sent to Java but the don't know about the additional line terminator. The codes misses the last line clearing the buffer. Using BufferedReader.readLine() solves this issue as the whole line, that's what acutally the console sends to java, so there's no line terminator left.

    What you mentioned about using a GUI to ask for data input instead of CLI is correct, but as said: When I started learning Java there was no Scanner as Java 5.0 wasn't released yet. It was still the days back when it was Java2SE 1.4.2. 1.5, what was advertised as "Java 5.0" in the installer, came a long time later.
     
    Campbell Ritchie
    Marshal
    Posts: 74632
    335
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    As I said earlier, the default delimiter is...

    jshell> new Scanner("Campbell").delimiter()
    $1 ==> \p{javaWhitespace}+

    A second call to nextInt() moves over the buffer ignoring the whilespace (including line ends) until it finds the next printing character. I have only ever had the problem with nextLine(). See this old post. I now repeat the reading until I get a non‑empty line; this is one way to do it:-Look! a while loop ending with ; but it will still work! I fancied writing some nguthy code, but the version I use is rather staider. The strip() method works in Java11+; in older versions use trim() instead.
     
    Campbell Ritchie
    Marshal
    Posts: 74632
    335
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I got so excited about my loop ending ; that I managed to introduce an error into my code. Sorry. I shall leave it as a challenge for people to find.
    reply
      Bookmark Topic Watch Topic
    • New Topic