简体   繁体   中英

How does returning a value work in a recursive method? [Java]

TLDR : java seems to only return the first value when the method is run. Am I wrong about this, or is there a workaround I'm not aware of [without resorting to loops] ?

My goal is to output the last value [boolean] from the return which gets assigned to the method, however I am unable to do it without a proper understanding of how return works.


Aim of the code is to return a boolean, from a simple choice [Y/N] by reading user input. If a wrong output [eg: "p","P","apples"] is given, the method should prompt the user again, until the right input is given.

This is what I started out with:

private Boolean nrCheck()
{   
    Scanner sc = new Scanner (System.in);
    Boolean isNewRelease;


    System.out.println("New Release [Y/N]? ");      
    String movieType = sc.nextLine();       

    switch (movieType)
    {
        case "Y" : case "y" :              isNewRelease = true;  break;
        case "N" : case "n" :              isNewRelease = false; break;
        default  : /*Try again*/ nrCheck();                      break; 
    }

    return isNewRelease;
}

Obviously this won't work, since the default case does not assign a value, resulting in an Initialization error.

Attempted to fix this by assigning a default value, like this :

private Boolean nrCheck()
{   
    Scanner sc = new Scanner (System.in);
    Boolean isNewRelease;


    System.out.println("New Release [Y/N]? ");      
    String movieType = sc.nextLine();       

    switch (movieType)
    {
        case "Y" : case "y" :        isNewRelease = true;            break;
        case "N" : case "n" :        isNewRelease = false;           break;
        default  : /*printTryagain*/ isNewRelease = null;  nrCheck();break; 
    }

    return isNewRelease;
}

This presents a new problem. For some reason, when I recall the method again, the return value is already set. I've tried to play around with the order of the code, and it doesn't really do much. My speculation is that once you recall the method, the return value is automatically set, and you cannot change it if set the first time.

And I am aware I could do this,

private Boolean nrCheck()
{   
    Scanner sc = new Scanner (System.in);
    Boolean isNewRelease;


    System.out.println("New Release [Y/N]? ");      
    String movieType = sc.nextLine();       

    do 
    {
        switch (movieType)
        {
            case "Y" : case "y" :        isNewRelease = true;            break;
            case "N" : case "n" :        isNewRelease = false;           break;
            default  : /*printTryagain*/ isNewRelease = null;  nrCheck();break; 
        }
    }
    while (movieType.equalsIgnoreCase("Y") || movieType.equalsIgnoreCase("N"))

    return isNewRelease;
}

But personally prefer not to unless I'm fully aware there isn't another solution, or there isn't a blatantly obvious error in my code. [Also want to extend this code to become a bit more general-purpose].

Ultimately, I want to be able to understand what mistake I have made, or if there isn't any, the limitations of return in this case, even if it means I have to scrap my code for a do-while loop.

You should return the value returned by the recursive call:

private boolean nrCheck()
{   
    Scanner sc = new Scanner (System.in);

    System.out.println("New Release [Y/N]? ");      
    String movieType = sc.nextLine();       

    switch (movieType)
    {
        case "Y" : case "y" : return true;
        case "N" : case "n" : return false;
        default  : return nrCheck();
    }
}

If you ignore that value, there's no point in making the recursive call in the first place.

PS, you can probably change the return type of the method to boolean , since it can never return null .

I don't think you even need recursion here, and it looks like you are understanding what it is used for incorrectly. Your third attempt with a do loop is the typical way you would poll a user for input:

private boolean nrCheck() {
    Scanner sc = new Scanner (System.in);
    boolean isNewRelease;

    System.out.println("New Release [Y/N]? ");      
    menuRedirect(movieType);    // don't know what this is doing...

    do {
        String movieType = sc.nextLine();
    } while (!movieType.equalsIgnoreCase("Y") && !movieType.equalsIgnoreCase("N"));

    // at this point, the movie type can only be y/Y/n/N
    isNewRelease = movieType.equalsIgnoreCase("Y") ? true : false;

    return isNewRelease;
}

Just Make Small Change In Your Method As Given Below

private Boolean nrCheck() {

    Scanner sc = new Scanner(System.in);
    Boolean isNewRelease = null;


    //While loop here which break only if isNewRelease value is 
    //Non null(true or false)
    while (isNewRelease == null) {

        System.out.println("New Release [Y/N]? ");
        String movieType = sc.nextLine();

        menuRedirect(movieType);

        switch (movieType) {
            case "Y":
            case "y":
                isNewRelease = true;
                break;
            case "N":
            case "n":
                isNewRelease = false;
                break;
            default:
                System.out.println("Try Again");
                /*I removed recursive call which not required because recursive calls always creates new stack frames so it is recommenced that if we are going to use such calls we need to go with tail recursion.*/    
                isNewRelease = null;
                break;
        }

    }

    return isNewRelease;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM