zoukankan      html  css  js  c++  java
  • scanner使用中遇见的问题

    近期在学习的过程中遇见一个问题,问题不难但还是须要去认真对待。

    先看看我写的源码

    	public static void main(String[] args){	
    		for(;;){
    			Scanner in = new Scanner(System.in);
    			System.out.println("-----");
    			int age = in.nextInt();
    			System.out.println("------");
    			in.close();
    			System.out.println(age>100);
    		}	
    	}
    在这段代码中。当第一次输入是不会有错,能正常执行;然后第二次循环报错。

    报出来的错误为:

    Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Scanner.java:838)
    at java.util.Scanner.next(Scanner.java:1461)
    at java.util.Scanner.nextInt(Scanner.java:2091)
    at java.util.Scanner.nextInt(Scanner.java:2050)
    at day01.Demo01.main(Demo01.java:11)

    看到这,感觉到相当的郁闷。当我们把in.close()这段代码给凝视掉的话。那这段代码能够无限的循环下去。

    可是从这段代码的逻辑来看,似乎没错,但机器给我们报出了错。这就须要我们去找到错误的。

    依据报出来的错,我们看到是int age = in.nextInt();这行代码出错。


    从这报出来的错误中来分析。简要的说,就是前后两次实例化的參数System.in是用一个对象,是InputStreamReader对象,每一个该对象包括一个StreamDecoder 实例 sd,private final StreamDecoder sd;  

    而in.close()方法为

    public void close() {   
           if (closed)   
               return;   
           if (source instanceof Closeable) {   
               try {   
                   ((Closeable)source).close();   
               } catch (IOException ioe) {   
                   lastException = ioe;   
               }   
           }   
           sourceClosed = true;   
           source = null;   
           closed = true;   
       }   


    当运行到 ((Closeable)source).close();就会进入InputStreamReader的close()方法:

    public void close() throws IOException {   
                    sd.close();   
     } 

    这里的sd就是上面提到的InputStreamReader对象,(又查了StreamDecoder 源码,但没更深入下去),此时sd已关闭。

    当运行如错误产生代码的第11行代码 in.nextInt()时。

    public int nextInt(int radix) {
            // Check cached result
            if ((typeCache != null) && (typeCache instanceof Integer)
    	    && this.radix == radix) {
                int val = ((Integer)typeCache).intValue();
                useTypeCache();
                return val;
            }
            setRadix(radix);
            clearCaches();
            // Search for next int
            try {
                String s = next(integerPattern());
                if (matcher.group(SIMPLE_GROUP_INDEX) == null)
                    s = processIntegerToken(s);
                return Integer.parseInt(s, radix);
            } catch (NumberFormatException nfe) {
                position = matcher.start(); // don't skip bad token
                throw new InputMismatchException(nfe.getMessage());
            }
        }
    当中调用了next()方法

    public String next(Pattern pattern) {
            ensureOpen();
            if (pattern == null)
                throw new NullPointerException();
    
            // Did we already find this pattern?
            if (hasNextPattern == pattern)
                return getCachedResult();
            clearCaches();
    
            // Search for the pattern
            while (true) {
                String token = getCompleteTokenInBuffer(pattern);
                if (token != null) {
                    matchValid = true;
                    skipped = false;
                    return token;
                }
                if (needInput)
                    readInput();
                else
                    throwFor();
            }
        }

    异常是从方法throwFor();中抛出,而异常的来源是readInput()方法

    private void readInput() {   
            if (buf.limit() == buf.capacity())   
                makeSpace();   
     
            // Prepare to receive data   
            int p = buf.position();   
            buf.position(buf.limit());   
            buf.limit(buf.capacity());   
     
            int n = 0;   
            try {   
                n = source.read(buf);   
            } catch (IOException ioe) {   
                lastException = ioe;   
                n = -1;   
            }   
     
            if (n == -1) {   
                sourceClosed = true;   
                needInput = false;   
            }   
     
            if (n > 0)   
                needInput = false;   
     
            // Restore current position and limit for reading   
            buf.limit(buf.position());   
            buf.position(p);   
        }  

    当运行到12行source.read()时,source是Reader类

    public int read(java.nio.CharBuffer target) throws IOException {   
        int len = target.remaining();   
        char[] cbuf = new char[len];   
        int n = read(cbuf, 0, len);   
        if (n > 0)   
            target.put(cbuf, 0, n);   
        return n;   
    } 

    在运行InputStreamReader的read方法

    public int read(char cbuf[], int offset, int length) throws IOException {   
                     return sd.read(cbuf, offset, length);   
    }  

    而该InputStreamReader实际上就是System.in。而之前的close()方法已经将sd关闭了,此处再次实行read方法。则抛出IOException。然后层层捕获,终于抛出.NoSuchElementException

     

    以上错误归根揭底,最基本的原因是System.in输入流已经关闭。




  • 相关阅读:
    jdk8:垃圾收集器
    Young GC和Full GC分别在什么情况下会发生?
    GC之Minor/Young/Major GC的区别
    Java的JJWT实现JWT
    什么是 JWT -- JSON WEB TOKEN
    Spring的两种动态代理:Jdk和Cglib 的区别和实现
    java对象结构 对象头 Markword
    偏向锁跟可重入性有什么区别
    C# 加密算法[汇总]
    Java语言:JAVA8 十大新特性详解(zz)
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7133108.html
Copyright © 2011-2022 走看看