Search code examples
javajava.util.scannerfileinputstream

Java Scanner not initializing in one string() even though it does in another one


The same type of scanner method is working in one place, but not in the other... I am using eclipse as my code editor if that changes any answers. All variables have been declared elsewhere if not here.

If anyone knows how to fix this, you will have my undying gratitude :)

This one is working:

private String questionPicker(String str) 
{
    question = (int)(Math.random()*42);
    System.out.println(question);
    fileChoose = str.toUpperCase();
    String returnee;
    
    Scanner is = null;
    try 
    {
        is = new Scanner(new FileInputStream("triviaQ"+fileChoose+".txt"));
    }
    catch(FileNotFoundException z)
    {
        System.out.println("Error 004: File retrieve failed.");
    }
    skipLines(is, question);
    returnee = is.nextLine();
    is.close();
    return returnee;
}

This one is not working:

public String getAnswer() 
{
    String returnee;
    
    Scanner ls = null;
    try 
    {
        ls = new Scanner(new FileInputStream("triviaA"+fileChoose+".txt"));
    }
    catch(FileNotFoundException z)
    {
        System.out.println("Error 004: File retrieve failed.");
    }
    skipLines(ls, question);
    returnee = ls.nextLine();
    ls.close();
    return returnee;
}

error message:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "java.util.Scanner.nextLine()" because "ls" is null
at jepp.JepQA.getAnswer(JepQA.java:60)
at jepp.JepGui.actionPerformed(JepGui.java:268)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6617)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
at java.desktop/java.awt.Component.processEvent(Component.java:6382)
at java.desktop/java.awt.Container.processEvent(Container.java:2264)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4993)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2322)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4934)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4563)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4504)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2308)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2773)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Solution

  • Just catching exceptions is not enough; you must also change the code path accordingly.

    Your code has the form:

    Scanner ls = null;
    try {
        ls = new Scanner(...);
    } catch(FileNotFoundException z) {
        // print error message
    }
    // do something with ls
    

    If the exception happens, execution continues after printing the error message and ls will still be null when the do something with ls code executes, which is why you got the NullPointerException.

    To fix, either exit the method on exception:

    Scanner ls = null;
    try {
        ls = new Scanner(...);
    } catch(FileNotFoundException z) {
        // print error message
        return;
    }
    // do something with ls
    

    Or move the code that uses ls inside the try:

    try {
        Scanner ls = new Scanner(...);
        // do something with ls
    } catch(FileNotFoundException z) {
        // print error message
    }
    

    Note also with the last version, not only do we save a line of code (assignment and declaration as one line), but the scope of ls is limited to the try block; limiting scope is good coding practice.