Scanner类的close()后重新开启,产生NullPointer错误

一、问题背景

先看以下代码

public class practice {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String input = sc.nextLine();
        System.out.println(input);
        sc.close();
        
        practice pra = new practice();
        pra.a();
        
        Scanner sc2 = new Scanner(System.in);
        input = sc2.nextLine();
        System.out.println(input);
        sc2.close();
    }

    public void a() {
        Scanner sc = new Scanner(System.in);
        String input = sc.nextLine();
        System.out.println(input);
        sc.close();
    }
}

乍一看似乎没有问题,main函数中首先使用了Scanner类读入,完成输出以后关闭了流,接着调用a,a中创建Scanner类再从命令行读入,关闭流。回到main函数重复操作。但是当我们运行的时候会发现
在这里插入图片描述
idea报错的原因时引用了空指针,发生错误的地方是a的nextLine()方法处,明明重新创建了一个类,这是为什么呢?

二、Scanner类

执行下列代码

public class practice {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println(sc);

        practice pra = new practice();
        pra.a();

        Scanner sc2 = new Scanner(System.in);
        System.out.println(sc2);
    }

    public void a() {
        Scanner sc = new Scanner(System.in);
        System.out.println(sc);
    }
}

得到输出:

java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match valid=false][need input=false][source closed=false][skipped=false][group separator=\,][decimal separator=\.][positive prefix=][negative prefix=\Q-\E][positive suffix=][negative suffix=][NaN string=\Q?\E][infinity string=\Q∞\E]
java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match valid=false][need input=false][source closed=false][skipped=false][group separator=\,][decimal separator=\.][positive prefix=][negative prefix=\Q-\E][positive suffix=][negative suffix=][NaN string=\Q?\E][infinity string=\Q∞\E]
java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match valid=false][need input=false][source closed=false][skipped=false][group separator=\,][decimal separator=\.][positive prefix=][negative prefix=\Q-\E][positive suffix=][negative suffix=][NaN string=\Q?\E][infinity string=\Q∞\E]

可以发现,即使创建了三个类,他们的指向也是相同的。也就是说,我们虽然在三个地方创建了Scanner类,用流的方式从命令行读入用户输入,但只要在一个地方关闭,后面的部分均无法重新开启或是使用这个流读入,即使重新创建了这个类。
那么这是为什么呢?
用idea进行跳转我们可以看到
在这里插入图片描述
可以看到这里使用了static修饰,也就是说运行以后,in是一个独例,所有使用System.in的均会指向同一块引用。这也就解释了为什么创建了不同的Scanner类,关闭的是同一个流,因为他们一开始初始化的时候就是输入的同一个流。
在这里插入图片描述

三、修改

那么如果我不想要占用过多的内存,子类也想要从命令行读入怎么办呢?毕竟流不关闭会占用大量的资源,能够尽早关闭是最好的。那么我们可以做以下的修改,把Scanner类当作参数传给子类即可

public class practice {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        practice pra = new practice();
        pra.a(sc);

		String input = sc.nextLine();
        System.out.println(input);
        sc.close();
    }

    public void a(Scanner sc) {
        String input = sc.nextLine();
        System.out.println(input);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值