zoukankan      html  css  js  c++  java
  • java.util.NoSuchElementException

    问题引入

    Java商店作业不同函数里需要获取用户输入,用Scanner的时候,出现了异常java.util.NoSuchElementException

    作业中代码模式如下,func1func2中都使用Scanner并关闭它。然后在main中依次调用func1func2func2产生异常。说func1func2其实不合适,应该加个括号.....…..懒得加了

    //Demo.java
    import java.util.Scanner;
    
    class Test{
    	void func1() {
    		Scanner sc=new Scanner(System.in);
    		
    		//输出用户输入,替代作业里的使用Scanner
    		System.out.print("Func1请输入内容:");
    		System.out.println("Func1输出"+sc.next());
    		
    		//关闭Scanner
    		sc.close();
    	}
    	
    	void func2() {
    		Scanner sc=new Scanner(System.in);
    		
    		//输出用户输入,替代作业里的使用Scanner
    		System.out.print("Func2请输入内容:");
    		System.out.println("Func2输出"+sc.nextInt());
    		
    		//关闭Scanner
    		sc.close();
    	}
    }
    public class Demo{
        public static void main(String[] args) {
    		Test t=new Test();
    		t.func1();
    		t.func2();
    	}
    }
    
    /*Console输出如下:
    
    Func1请输入内容:小姐,请问你喜欢吃青椒吗?
    Func1输出:小姐,请问你喜欢吃青椒吗?
    Func2请输入内容:Exception in thread "main" java.util.NoSuchElementException
    	at java.base/java.util.Scanner.throwFor(Unknown Source)
    	at java.base/java.util.Scanner.next(Unknown Source)
    	at java.base/java.util.Scanner.nextInt(Unknown Source)
    	at java.base/java.util.Scanner.nextInt(Unknown Source)
    	at Test.func2(Demo.java:21)
    	at Demo.main(Demo.java:31)
    
    
    */
    

    异常产生原因

    func1sc.close();语句关闭了Scannerfunc2中使用Scanner产生异常

    因为System.inSystem类的静态成员,所以不同Scanner对象内的in是同一个in`

    func1func2中都用System.in创建了Scanner

    func1打开Scanner后将其关闭,这里间接地将System.in也关闭了

    func1结束后运行func2,这时再调用nextInt,在System.in已经关闭了的情况下,不能读取到任何数据,就会产生 java.util.NoSuchElementException

    解决方法

    系统资源一旦释放就不能再开启了,所以只有确定不在使用系统的时候,才能将流关闭

    所以应该在整个程序结束时释放Scanner等资源,而不是某个函数中每次使用Scanner等资源后都释放一次

    问题引入中的代码只是个模式,上边的两句话用在作业实际代码里就好了

    代码分析

    Scanner()

    创建Scanner对象代码为Scanner sc=new Scanner(System.in);构造函数源码如下

    public Scanner(InputStream source) {
            this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }
    

    可看出是调用了另外一个构造函数,继续查看源码

    private Scanner(Readable source, Pattern pattern) {
            assert source != null : "source should not be null";
            assert pattern != null : "pattern should not be null";
            this.source = source;	//看这句
            delimPattern = pattern;
            buf = CharBuffer.allocate(BUFFER_SIZE);
            buf.limit(0);
            matcher = delimPattern.matcher(buf);
            matcher.useTransparentBounds(true);
            matcher.useAnchoringBounds(false);
            useLocale(Locale.getDefault(Locale.Category.FORMAT));
        }
    

    至少知道了Scanner内部还是用到了流,算是对流进行了封装吧,使用起来更方便一些

    close()

    调用语句为sc.close();,查看close()源码,如下

    public void close() {
            if (closed)                             //1.通过closed标志校验Scanner是否已关闭;
                return;
            if (source instanceof Closeable) {      //2.执行source的close()方法,
                try {                               //将source关闭(这里为System.in);
                    ((Closeable)source).close();
                } catch (IOException ioe) {
                    lastException = ioe;
                }
            }
            sourceClosed = true;    //3.将sourceClosed标志设置为true,表示source已关闭;
            source = null;          //4.将source置为null,不再引用,处于可回收状态;
            closed = true;          //5.将closed标志设置为true,表示Scanner已关闭;
    }
    

    可以知道关闭Scanner的时候,((Closeable)source).close();System.in关闭了

    关闭后下次想再使用就当然有错了~(除非构造函数里还再把in给打开,但这样也不太合理)

    其实如果还可以再仔细看看Scanner的构造方法,和Scannernext(),能力有限,点到为止

    作者:@臭咸鱼

    本文为作者原创,转载请注明出处:https://chouxianyu.github.io/2018/11/03/java.util.NoSuchElementException/#more

    欢迎转发和评论

  • 相关阅读:
    在浏览器中输入url后执行的全过程
    自己搭建一个类似vue,实现响应式的原理
    关于vue是怎么放到服务器上运行的基于vue-cli3
    vue v-modal语法糖
    js中的Map和Set
    js的reduce方法
    vue双向绑定原理
    js对象原型-class类
    (二)仅仅通过Application监听用户行为及App的在线状态和在线时长
    (一)仅仅用ApplicationContext加载界面
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/11270042.html
Copyright © 2011-2022 走看看