3

最近、ユーザー定義クラスをスキャナーへの入力として渡すことについての本を読みましたが、その背後にあるロジックについてはあまり説明されていませんでした。ここにプログラムがあります

import java.nio.CharBuffer;
import java.util.Random;
import java.util.Scanner;

class ScannerInputBase implements Readable
{
    private int count;
    Random rand = new Random();
    ScannerInputBase(int count) { this.count = count; }
    public int read(CharBuffer cb)      //read is a method in Readable interface
    {
        if(count-- == 0)
        return -1;

        for(int i=0;i<2;i++)
        { cb.append('a'); }
        return 1;
    }
}

public class ScannerInput {

    public static void main (String args[]) {
        Scanner input = new Scanner(new ScannerInputBase(5));

        while(input.hasNext()) 
        {
            print(input.next()+"-");
        }
    }
}

そしてその出力は

aaaaaaaaaa- 

ここで2つの質問があります

  1. ここで read() 関数がどのように呼び出されるのですか?
    つまり、どういうわけか暗黙のうちに呼び出されていることを理解していますが、どこから呼び出されているのかを理解しています。

  2. 出力内の 1 つのハイフンは、main 関数の while ループが 1 回だけ繰り返されることを示しています。しかし、なぜ一度だけ。aa-aa-aa-aa-aa- のような出力を期待していました

4

2 に答える 2

2

ここで read() 関数がどのように呼び出されるのですか? つまり、どういうわけか暗黙のうちに呼び出されていることを理解していますが、どこから呼び出されているのかを理解しています。

答えは、Scannerメソッドのクラスのソース コードにありnext()ます。

public String next() {
    ....
    while (true) {
     .....
     if (needInput)
         readInput();
     ...
    }
}

これreadInputにより、次のように定義されたメソッドに移動します。

private void readInput() {
    ......
     try {
         n = source.read(buf);
     } catch (IOException ioe) {
    .....
     }
    .....
 }

メソッドがクラスのインスタンスであるオブジェクトのメソッドをreadInput呼び出しており、のオブジェクト作成中にコンストラクターに引数として渡されていることがわかります。さて、 のサブクラスのオブジェクトを引数としてコンストラクタに渡したので。また、クラス内でメソッドをオーバーライドしたため、メソッドのオーバーライドされたバージョンがメソッドによって呼び出されています。readsourceReaderScannerScannerReaderScannerread(CharBuffer)readScanner.readinput

出力内の単一のハイフンは、main 関数の while ループが 1 回だけ繰り返されることを示しています。しかし、なぜ一度だけ。aa-aa-aa-aa-aa- のような出力を期待していました

aaaaaaaaaaのため、デフォルトの区切り文字パターンである文字列には空白がありません。その結果、すべての文字列が 1 回の反復で読み取られます。そのため、hasNext最初の繰り返しの後に false を返し、while ループが終了します。

注:@Overrideサブクラス内のメソッドをオーバーライドするときは、常に注釈を使用してください。

于 2013-08-15T11:04:24.860 に答える
0

Scanner クラスは、データを読み書きするためのストリームのラッパー クラスです。いくつかのオーバーロードされたコンストラクターがあります。あなたの場合:

public Scanner(Readable source) {
        this(source, WHITESPACE_PATTERN);
    }

が呼び出されます。interface Readableメソッドが 1 つしかないためread(CharBuffer cb)ScannerInputBaseは Readable のインスタンスであるため、Scanner オブジェクトは Readable が渡されたものの read() メソッドを呼び出すだけです。

2番目の点については、のドキュメントを見てくださいnext()

このスキャナーから次の完全なトークンを検索して返します。完全なトークンの前後には、区切り文字パターンに一致する入力が続きます。以前の hasNext() の呼び出しで true が返された場合でも、このメソッドは入力がスキャンされるのを待っている間にブロックされる場合があります。

使用されるデフォルトのパターンは次のとおりです。

Pattern WHITESPACE_PATTERN = Pattern.compile(
                                                "\\p{javaWhitespace}+");

SO、スキャナーの next() 呼び出しは、複数のread()呼び出しを行うことですべてを一度に読み取ります。

于 2013-08-15T10:55:22.187 に答える