2

Possible Duplicate:
How do I compare strings in Java?

I am having trouble understanding how to use a Java switch statement. After executing a method in one of the case statements, it still then goes to the default statement and runs that too. Here's the code:

Scanner scanner = new Scanner(System.in);
String option = null;

while (option != "5") {
    ShowMenu();
    option = scanner.nextLine();
    switch (option) {
        case "1": ViewAllProducts(); break;
        case "2": ViewProductDetails(scanner); break;
        case "3": DeleteProduct(scanner); break;
        case "4": AddProduct(scanner); break;
        case "5": break;
        default: System.out.println("Invalid option. Please try again."); break;
    }
}

The above code is in the main method. After running case "4" for example, it prints "Invalid option."

Community
  • 1
  • 1
Matt
  • 6,787
  • 11
  • 65
  • 112
  • 1
    Must be `while(!"5".equals(option)) { }` – KV Prajapati Sep 22 '12 at 09:03
  • Wow. thanks everyone.. for me being a C# coder, this is very strange.. we don't have this problem in C#. The above wouldn't be a problem at all. Very interesting LOL. – Matt Sep 22 '12 at 09:09
  • Problem is reference equality vs value equality and C# do have this problem as well but fortunately String in C# overloads `==` operator. – Premraj Sep 22 '12 at 09:29
  • This could possibly be because, in your method you are using the scanner passed to read some input from, preferably using the method `scanner.nextInt()` or `scanner.next()`. See [Scanner.next()](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html#next%28%29) and [Scanner.nextLine()](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html#nextLine%28%29) for more details. – Rohit Jain Sep 23 '12 at 01:00
  • According to the docs, if you use `scanner.next()` or `scanner.nextInt()` methods, then you read the input till the end of the line, but `Skipping` the last `NewLine` character. Thus, if you have a `scanner.nextLine()` immediately after `scanner.next()`, your nextLine() will read the next character `NewLine` left out by `scanner.next()` and read it as one line(empty though). And then your next `scanner.nextLine()` will read the line you expected the first one to read.. So it will seem that your call to `scanner.nextLine()` skipped to the next call.. – Rohit Jain Sep 23 '12 at 01:05
  • @Matt.. Still figuring out, why you passed the Scanner reference to your methods at the first place?? – Rohit Jain Sep 23 '12 at 01:07
  • @Rohit Jain, nice one.. submit above as answer and I will accept it. By the way, exactly what's wrong with wanting to reuse the Scanner variable instead of recreating it in each function? – Matt Sep 23 '12 at 01:12
  • @Matt.. Well, that is what I just explained.. There is nothing wrong, but it may give you wierd output. Still, if you want to pass it, you can re-initialize it at the time of reading more option.. – Rohit Jain Sep 23 '12 at 01:16
  • Stack Overflow is a Q&A archive, not a personal debugging helpdesk. Your question is expected to contribute to the knowledge of humanity by being useful for someone else at some later date. This means that when you ask several questions based on the previous ", (Point to my syntax error, now my problem is THIS, now my problem is THIS, now my problem is THIS), you are being harmful to others. Please ask ONE question, not five in one. – Eric Leschinski Aug 25 '13 at 12:31
  • @EricLeschinski, there's no need to be condescending and you're welcome to your opinion, but I disagree with you. The various updates that I added helped communicate my progress with the problem so that those who were helping me solve it did not continue down the wrong track. Also, you removed the final update which is what the solution actually was and thus, anyone having the same problem may not see this now... – Matt Aug 26 '13 at 09:11
  • ..@Rohit Jain saw this final comment and gave further information as to why that was the solution (as I still did not understand it fully). And as for harming others, you are the only one here who has complained (and a year after the question was answered). I suggest that if you want to make yourself useful, you go answer someone's current questions instead. If you must insist on editing old posts, at least refrain from offensive comments. Thank you. – Matt Aug 26 '13 at 09:11
  • @EricLeschinski, by the way, I have often found such posts as this (where the OP has updated the situation) to be very useful to me personally. I am sure there are some others that feel the same. – Matt Aug 26 '13 at 09:14

6 Answers6

7
  while (!option.equals("5")){...}

Use .equals() for string compare.

== compare string refrences(Memory location) .equals() compare string value

Community
  • 1
  • 1
Samir Mangroliya
  • 39,918
  • 16
  • 117
  • 134
6

You are comparing Strings with == in your while condition (which compares references instead of values - use equals method for value equality), while loop should be changed to following -

while (!option.equals("5"))

It works in C# flawlessly because of operator overloading while operator overloading is not allowed in java (though "+" is overloaded for String and numbers)

Community
  • 1
  • 1
Premraj
  • 7,802
  • 8
  • 45
  • 66
  • Thanks for the correct answer, but it would be more helpful if you also explained why. So, I will +1 for you for being the first, but Samir gets marked as "answer" – Matt Sep 22 '12 at 09:11
  • @Matt - Its ok.. I still added the clarification :) – Premraj Sep 22 '12 at 09:30
  • please see my edit. This is not resolved yet. – Matt Sep 22 '12 at 09:40
  • @Matt please replace your println in default case with - `System.out.println("Invalid option. Please try again...'"+option+"'")` and update the question with the output – Premraj Sep 22 '12 at 09:45
1

I think the problem is in the condition of while loop. Can you change the condition to while(!"5".equals(option)) and then try running the problem.

Hope this helps you.

Japan Trivedi
  • 4,445
  • 2
  • 23
  • 44
1

Your scanner.nextLine() should be outside your while. And generally do-while is used better in combination with switch-case.. So, you can better go with it..

A general use of do-while with switch-case, when you are reading from user is like this: -

boolean flag = false;
do {
    String option = scanner.nextLine();
    switch (option) {
        case "1": break;
        case "2": break;
        default : flag = true;
                  break;
    }
} while(! flag);

And one important thing to know is: - Strings are Immutable in Java..

Generally for String comparisons in Java, you should use equals() function if you want to compare their values.. And also, I suggest you to override this equals() and hashcode() methods in your class (In future if you make one), to compare two instances of your class..

Actually, there is a big difference between == and equals(). It actually depends on how you are creating your string.. For E.g., suppose this is your code: -

String a = "5"; 
String b = new String("5");
String c = "5"; or String c = a;

System.out.println("a == b?" + (a == b));  // Will Print false
System.out.println("a.equals(b)?" + a.equals(b));   // Will Print true..

System.out.println("a == c?" + (a == c));  // Will Print true
System.out.println("a.equals(c)?" + a.equals(c));   // Will Print true..

In the above code, your String references 'a' and 'c' are pointing to the same object represented by "5". Whereas the reference "b" is pointing to a different object "5", because using "new" operator to create a String always creates a new Object..

Now, == operator checks whether the two String reference being compared points to the same object or different, whereas equals() function compares the actual value contained by the two string objects..

So, the output in the program will be clear now.. I just explained this because, in your while, you will have to use equals() function to check whether your "option" reference has the same value as "5".

Now, I think you can change your code a little bit, and preferably use do-while to get required output..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
1

I am modifying your code to re-initialize your scanner reference before reading new option..

    Scanner scanner = new Scanner(System.in);
    String option = null;

    ShowMenu();
    option = scanner.nextLine();

    while (!"5".equals(option)) {
        switch (option) {
            case "1": ViewAllProducts(); break;
            case "2": ViewProductDetails(scanner); break;
            case "3": DeleteProduct(scanner); break;
            case "4": AddProduct(scanner); break;
            case "5": break;
            default: System.out.println("Invalid option. Please try again..."); break;
        }
        ShowMenu();
        scanner = new Scanner(System.in);  // Add this here

        option = scanner.nextLine();    // Use brand new scanner without any problem..
    }

Rest, you can read from the link I provided, to know the difference between various methods for reading user input..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
0

I stopped passing scanner to each function and created a new one inside each function instead. That fixed the problem. So, I figured out that problem.. but, I want to know why..

If you posted an SSCE, we could probably answer that. Unfortunately, the behaviour you are describing involves code that you haven't shown us.

is this a bug in Java or normal?

It is highly unlikely that this is a Java bug. The Scanner code has been in Java for a few years, and any significant bugs are likely to have been encountered before and fixed.

On the other hand, I can think of no reason why passing a Scanner to a method would make any difference per se.

But the bottom line is that without an SSCE it is not possible to figure out what your code is really doing ... and explain the root cause.

If I can understand why this is a problem then I can avoid it in future with other classes too.. unless this only happens with Scanner?

Without an SSCE we can't help you understand.

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