【java】 Scanner类读取控制台输入内容研究

对于用Eclipse工具进行开发的程序员来说,开始学习JAVA的时候,我们会用到java.util.Scanner类来模拟界面手动输入操作,比如下面的这段代码

一个让我很感兴趣的事情是,控制台输入,程序也能读取到,这是怎么办到的呢,现在让我们开启追踪模式,先找个简单的程序一行一行的去分析下,先看程序

那我们就看红框标注内的这行代码,进入Scanner的构造器System.in就是一个InputStream  in对象,看下面的代码

红框标注内,输入流in被初始化成了InputStreamReader,再进入到InputStreamReader的构造器,看下面的代码

有几处红框标注,后面会用到,现在接着看,通过初始化InputStreamReader,把第二个红框标注内StreamDecoder进行了实例化sd,到此我们知道他们背地里干的什么事情,然后我们再返回来到

public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
}
这段代码告诉我们要跳转到Scanner的另一个构造器,看下面的代码

这个就是真正要初始化Scanner的老窝了,this.source 就是InputStreamReader,到这里,开头的第一句代码就完事了。

我们再来看一下

红框标注内的代码,进入到nextLine()方法内部,继续看代码

上面红框内应该就是我们的核心代码了,继续往下看,进入到findWithinHorizon方法内部


     这段代码比较有意思,第一个是绿框的内容,程序用了一个while(true)死循环,保证线程一直运行,为了等我们输入,用户线程一直等待,够哥们,  另一个是红框内的内容,needInput是个是否输入标识,如果是true的化,就会执行readInput(),这个方法就是要读取我们的输入内容,核心要接近了,再给自己点耐心,继续看代码,哈哈



红框标注内的就是调用InputStreamReader的read(java.nio.CharBuffer target) ,InputStreamReader继承的Reader,read方法是父类Reader的,

图中的第二个红框就是读取数据了,调用的是Reader的read(char cbuf[], int off, int len)方法,看看那个方法是啥样的呢

abstract public int read(char cbuf[], int off, int len) throws IOException;
怎么是个抽象类呢,InputStreamReader继承的Reader,所以实现了该方法,看实现代码段

public int read(char cbuf[], int offset, int length) throws IOException {
   return sd.read(cbuf, offset, length);
}
原来读取调用的是InputStreamReader里面的StreamDecoder  sd,  开始的时候我们提到过后面要用的,叫你藏,我找到你了

StreamDecoder的read方法你是怎么玩的呢,继续看代码

public int read(char ac[], int i, int j)
        throws IOException
    {
        int k = i;
        int l = j;
        Object obj = lock;
        JVM INSTR monitorenter ;
        ensureOpen();
        if(k < 0 || k > ac.length || l < 0 || k + l > ac.length || k + l < 0)
            throw new IndexOutOfBoundsException();
        if(l == 0)
            return 0;
        int i1 = 0;
        if(!haveLeftoverChar) goto _L2; else goto _L1
_L1:
        ac[k] = leftoverChar;
        k++;
        l--;
        haveLeftoverChar = false;
        i1 = 1;
        if(l != 0 && implReady()) goto _L2; else goto _L3
_L3:
        i1;
        obj;
        JVM INSTR monitorexit ;
        return;
_L2:
        if(l != 1) goto _L5; else goto _L4
_L4:
        int j1 = read0();
        if(j1 != -1) goto _L7; else goto _L6
_L6:
        i1 != 0 ? i1 : -1;
        obj;
        JVM INSTR monitorexit ;
        return;
_L7:
        ac[k] = (char)j1;
        i1 + 1;
        obj;
        JVM INSTR monitorexit ;
        return;
_L5:
        i1 + implRead(ac, k, k + l);
        obj;
        JVM INSTR monitorexit ;
        return;
        Exception exception;
        exception;
        throw exception;
}
看看这代码,原来用到了虚拟机的东西了,终于恍然大悟了,   为啥控制台等待我们的输入

 JVM INSTR monitorenter ;
原来虚拟机有个监控器,在监视我们的输入内容,只要我们输入了,一回车,就读取到了CharBuffer中了
 JVM INSTR monitorexit ;
虚拟机的监控器就退出了,然后我们就能读取到了内容了,我们开始的String next = sc.nextLine(); 就得到了结果。

虚拟机的东西慢慢也研究起来,暂时就是分享到这了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

门主冬七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值