7
0

More than 1 year has passed since last update.

[英語が苦手な人向け]英語でのググり方(JavaのScannerクラスのコンストラクタにSystem.inを入れた場合にCloseするべきか?問題を添えて)

Last updated at Posted at 2021-12-14

ググって解決しづらかったこと Advent Calendar 2021 14日目の記事です。
すみません遅刻しました (_ _。)

はじめに

Q 英語が苦手です。 英語でググれません。無理です。
A そこにGoogle翻訳があるじゃろ。

英語苦手でも以外と検索できますという事を伝えたかった

茶番を飛ばして結論読みたい方

茶番

後輩くん)うーん?
先輩さん)どうしました後輩くん?
後輩くん)ちょっとこのコードを見て下さい。

package test_java;

import java.util.Scanner;

public class App {

    public static void main(String[] args) {
        var s = new Scanner(System.in);
        var input = s.nextLine();
        System.out.println(input);
        s.close();
    }
}

先輩さん)標準入力から文字列を取得して表示するJavaのプログラムですね…… これがどうしたんですか?
後輩くん)この間「Javaの講義でScannerクラスを使った場合は必ずCloseするように」と指導されたんです。
後輩くん)でもScannerクラスのコンストラクタにSystem.in入れた場合はどうすれば良いか分からなくて……
後輩くん)System.inは標準入力で一度閉じたら開け無いので閉じるなと別の方に言われたんです。でもScannerはCloseしなきゃならないわけで、
後輩くん)それで「Scanner system.in close するべきか」で、ググったんですけど……こんな結果に……
先輩さん)ふむ

image.png

主な検索結果

サイト 結論
[解説] Scannerのclose()は必要? 書かなくても良いけど練習に最後にCloseしよう
[Qiita]標準入力のScannerを1度closeしたら、2度と標準入力できない理由を調べた 標準入力ストリームはプログラム終了時に自動的に閉じるから、明示的に閉じる必要はない(推測)
[Y知恵袋]javaで、Scannerのcloseは必要なのですか? 一人目 標準入力以外なら必要。
二人目 newしたら必ずCloseする癖をつけましょう
三人目 理想的にはClose、省略しても暗黙的に
[Y知恵袋]「リソースリークがこのロケーションで閉じられていません」という警告が出て困っています。 System.inは閉じてしまうとそれ以降のプログラムで使え無くなるので管理はJVMに任せよう(閉じない)

先輩さん)とりあえず、ScannerをSystem.inで開いた場合は、自動でCloseするので手動ではしなくて良くて良さそうですね。やるにしても最後にすれば
後輩くん)でも理想を言えば書くべきだからmain関数の最後に書けば良いと……ん?でもmain関数以外でScanner使う場合どうすれば良いんでしょう。インスタンスは作っても閉じれませんし……閉じたいけど閉じれない……

先輩さん)じゃあ英語でググって見ましょう!!
後輩くん)え?悪い意味での自慢になりますが、僕英語できませんよ?
先輩さん)いや書けるよ?
後輩くん)え?
先輩さん)とりあえず検索ワードから日本語を消して……「Scanner system.in close」
先輩さん)ほら、もう英語になった

image.png

後輩くん)さっきと同じじゃないですか?
先輩さん)(こいつ、無意識に英語の検索結果を無視してる!?)
先輩さん)こんな時は、Google翻訳を使って……(urlコピーして、google翻訳に貼り付けて…)こうじゃ!!
Screenshot 2021-12-15 at 00-05-01 Google 翻訳.png

image.png

後輩くん)二回目の検索結果の二番目の項目ですね…… System.inを閉じずにスキャナーを閉じます!!
先輩さん)開いてみますか……クリックできない?それなら翻訳元のURLから飛んでGoogleChromeの翻訳機能を使えば……

原文

Close Scanner without closing System.in

I'm trying to re-factor a large and frequently used part of my application into separate methods to make it easier to maintain.

Some of these methods asks the user for input and does input validation, so I've used a Scanner and System.in But when I close my Scanner I also close System.in

So my question is, can I only prevent System.in being closed by shielding it with CloseShieldInputStream or should I just start passing a Scanner to the methods?

Simply use a custom FilterInputStream instead of System.in:

new FilterInputStream(System.in) {
@Override
public void close() throws IOException {
//don't close System.in!
}
}

約(Google Chrome)

System.inを閉じずにスキャナーを閉じます

アプリケーションの大規模で頻繁に使用される部分を個別のメソッドにリファクタリングして、保守を容易にしようとしています。

これらのメソッドのいくつかは、ユーザーに入力を要求し、入力の検証を行うため、ScannerとSystem.inを使用しましたが、Scannerを閉じると、System.inも閉じます。

だから私の質問は、CloseShieldInputStreamでシールドすることによってのみSystem.inが閉じられるのを防ぐことができますか、それともメソッドにスキャナーを渡すことを開始する必要がありますか?

System.inの代わりにカスタムFilterInputStreamを使用するだけです。

new FilterInputStream(System.in) {
@Override
public void close() throws IOException {
//don't close System.in!
}
}

後輩くん)求めてた答えだ!!
先輩さん)ちょっとまってその下も読んで

原文

This is pretty much what commons' CloseShieldInputStream does and if you end up this position, you may want to have another look at the design of your software. A solution like this shouldn't be needed unless you're working with third-party solutions.

約(Google Chrome)

これは、commonsのCloseShieldInputStreamが行うこととほぼ同じであり、この位置にたどり着いた場合は、ソフトウェアの設計をもう一度確認することをお勧めします。サードパーティのソリューションを使用している場合を除いて、このようなソリューションは必要ありません。(ここのすべての答えに適用されます)

後輩くん)要らないの??

先輩さん)別のも読んでみますか…おっと気になる記述が

原文

By the way, it is a bad idea to instantiate new Scanner(System.in) more than once. The problem is that a Scanner may read any or all type-ahead. If you have two or more of them wrapping the same underlying stream, one Scanner can capture input that a later one needs to read. This can lead to occasional unexpected behavior, and is likely to cause your application to fail if standard input is redirected ... at the shell level.

約(Google Chrome)

ちなみに、new Scanner(System.in)複数回インスタンス化するのは悪い考えです。問題は、Scannerが一部またはすべての先行入力を読み取る可能性があることです。それらの2つ以上が同じ基になるストリームをラップしてScannerいる場合、後で読み取る必要がある入力をキャプチャできます。これにより、予期しない動作が発生する可能性があり、シェルレベルで標準入力がリダイレクトされると、アプリケーションが失敗する可能性があります。

先輩さん)一つだけScanner作って使い回せば?
後輩くん)それが良さそうですね……関数内でScanner作るのはやめて引数で取るようにします!!

補足&まとめ

  1. プログラミング学んできている人は英語は書けなくても多少知っている単語だけでも検索できる
  2. 知らない単語ならGoogle翻訳で確認(補足)
  3. 英語記事も翻訳ソフト(Google Chromeのサイト翻訳機能がおすすめ)を使えば以外と読める(補足)
  4. 英語で調べると日本語だと知る事のできなかった知識も手に入れる事ができる(補足)
  5. Chromeが翻訳してくれないサイトは、URLをコピーしてgoogle翻訳に貼り付けるとサイトごと翻訳してくれる
  6. google翻訳のサイト翻訳はリンクが機能しない事がある
7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0