-4

Context

I have a Java CLA, built in IntelliJ and managed with Gradle. The user enters a number in a given menu to add/change/view contacts, and exit.

Problem

There is an issue with the switch statement default break. If the program runs and you select the default, it breaks as expected.

However, if you choose another case first and then try to break, it calls displayContacts first, and when you return to the menu and break again, it throws the following:

Execution failed for task ':Main.main()'. Process 'command '/Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/bin/java'' finished with non-zero exit value 1

The switch statement should never call this method; why is this happening, and what's causing this error?

Main Class

import java.util.ArrayList;

public class Main {

    static Input input = new Input();
    static ArrayList<Contact> contactList = new ArrayList<Contact>();

    public static void main(String[] args) {
        showMenu();
    }

    public static void showMenu() {
        printMenuOptions();
        switch (input.menuChoice()) {
            case 1: {
                newContact();
                break;
            }
            case 2: {
                updateExistingContact();
                break;
            }
            case 3: {
                showContact();
                break;
            }
            default: break;
        }
    }

    static void printMenuOptions() {
        System.out.println("Welcome to Contact Manager");
        System.out.println("Please select an option:");
        System.out.println("1. Create new Contact");
        System.out.println("2. Update Contact");
        System.out.println("3. View Contact");
        System.out.println("4. Exit");
    }

    static void newContact() {
        contactList.add(new Contact(input.confirmInput("first name"), input.confirmInput("last name"), input.confirmInput("address"), input.confirmInput("phone number"), input.confirmInput("DOB in dd/mm/yyyy format"), input.confirmInput("email")));
        showMenu();
    }

    static void updateExistingContact() {
        checkForContacts();
        displayContacts();
        try {
            updateContactFields(contactList.get(Integer.parseInt(input.confirmInput("contact choice")) - 1));
        } catch (Exception e) {
            System.out.println("No such contact");
            showMenu();
        }
    }

    static void checkForContacts() {
        if (contactList.size() == 0) {
            System.out.println("There are no contacts yet");
            showMenu();
        }
    }

    static void updateContactFields(Contact contact) {
        System.out.println("Currently: " + contact.returnFirstName());
        contact.updateFirstName(input.confirmInput("first name"));
        System.out.println("Currently: " + contact.returnLastName());
        contact.updateLastName(input.confirmInput("last name"));
        System.out.println("Currently: " + contact.returnAddress());
        contact.updateAddress(input.confirmInput("address"));
        System.out.println("Currently: " + contact.returnPhoneNumber());
        contact.updatePhoneNumber(input.confirmInput("phone number"));
        System.out.println("Currently: " + contact.returnDOB());
        contact.updateDOB(input.confirmInput("DOB in dd/mm/yyyy format"));
        System.out.println("Currently: " + contact.returnEmail());
        contact.updateEmail(input.confirmInput("email"));
        showMenu();
    }

    static void showContact() {
        checkForContacts();
        displayContacts();
        Contact contact = null;
        try {
            contact = selectContact(contactList.get(input.contactChoice() - 1));
        } catch (Exception e) {
            System.out.println("No such contact");
            showMenu();
        }
        printContactDetails(contact);
        showMenu();
    }

    static void printContactDetails(Contact contact) {
        System.out.println("First name is: " + contact.returnFirstName());
        System.out.println("Last name is: " + contact.returnLastName());
        System.out.println("Address is: " + contact.returnAddress());
        System.out.println("Phone number is: " + contact.returnPhoneNumber());
        System.out.println("Date of birth is: " + contact.returnDOB());
        System.out.println("Email is: " + contact.returnEmail());
    }

    static Contact selectContact(Contact contact) {
        return contact;
    }

    static void displayContacts() {
        System.out.println("Please select a contact");
        for (int i = 0; i < contactList.size(); i++) {
            System.out.println(i + 1);
        }
    }
}

Input menuChoice()

    public Integer menuChoice() {
        Scanner userInput = new Scanner(System.in);
        String input = userInput.nextLine();
        try {
            return Integer.parseInt(input);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

Edit: Added break statements to each case. Edit 2: Found that the issue is to do with the input class, apparently the Scanner result isn't consumed so it keeps being used.

Jules
  • 303
  • 2
  • 13
  • 1
    Are you aware that you need to a `break` in each case of the switch statement? – Sweeper Feb 27 '20 at 10:30
  • 1
    You need a break in each case. The one in default is not helping you. – khelwood Feb 27 '20 at 10:30
  • You need to call `break` after all the `case`s, otherwise all subsequent `case`s are executed as well. – f1sh Feb 27 '20 at 10:31
  • 1
    Does this answer your question? [Why do we need break after case statements?](https://stackoverflow.com/questions/2710300/why-do-we-need-break-after-case-statements) – OH GOD SPIDERS Feb 27 '20 at 10:32
  • The `default` case here *does* issue a `break`, and does *not* call a method, but all the other cases do the opposite. Don't use unexplained TLAs here. – user207421 Feb 27 '20 at 10:32
  • https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html – edwgiz Feb 27 '20 at 10:33
  • I've added breaks as suggested, it behaves in the same way. – Jules Feb 27 '20 at 10:35
  • The only way you can get the message you quote is by calling `System.exit(1)`. There is none such in your code. *Ergo* this isn't the real code. – user207421 Feb 27 '20 at 11:20
  • @Jules - If one of the answers resolved your issue, you can help the community by marking it as accepted. An accepted answer helps future visitors use the solution confidently. Check https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work to learn how to do it. – Arvind Kumar Avinash May 23 '20 at 09:55

2 Answers2

1

It's normal for switch-case expressions that they 'fall through'. So we have to break after each case, if we don't want the others being executed too.

    switch (input.menuChoice()) {
        case 1: {
              newContact();
              break;
        }
        case 2: {
              updateExistingContact();
              break;
        }
        case 3: {
              showContact();
              break;
        }
        default: break;
    }
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • I've implemented the breaks in each case as suggested, and I still have the same issue. Any further thoughts? – Jules Feb 27 '20 at 10:36
0

If you want to execute only one case then you have to add break statement and if you not add break statement after calling the method then all will execute (**and in that i think there is no need of switch case)**

switch (input.menuChoice()) {
        case 1:
              newContact();
              break;
        case 2:
              updateExistingContact();
              break;
        case 3:
              showContact();
              break;
        default: break;
    }
user207421
  • 305,947
  • 44
  • 307
  • 483
Bhushan
  • 104
  • 1
  • 9