您的位置:首页 > 编程语言 > Java开发

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

2018-01-16 11:59 507 查看
对于用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(); 就得到了结果。

虚拟机的东西慢慢也研究起来,暂时就是分享到这了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: