初心者の質問です。
ある時ふと、思ったのですが、javaで
String a="あいうえお";
System.out.println(a);
みたいに記述するとStringクラス型の変数aに格納されている参照値を読み込んで
参照番地のメモリ?から文字列を参照していると解釈しているのですが、
上のコードの'a'は参照型の変数ですよね?
BufferedReader br = new BufferedReader();
でいう所の'br'と区分的には同じだと思っているのですが、
なぜ、参照型の変数である'a'だけをSystem.out.printlnに入れるだけで
文字を出力できているのでしょうか。(メソッド名が必要ない?)
Stringクラスの中の何を呼び出しているのでしょうか?
BufferedReaderクラスでは同じようなことはできませんよね。
Stringクラスは、他のクラスとは根本的になにかが違うのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
String a="あいうえお";
...
上のコードの'a'は参照型の変数ですよね?
そうですね。String
クラスのインスタンスへの参照を収める変数です。
なぜ、参照型の変数である'a'だけをSystem.out.printlnに入れるだけで
文字を出力できているのでしょうか。(メソッド名が必要ない?)
色々な疑問が湧いてしまったようですが、それぞれは関連していて、また、Javaと言うプログラミング言語を理解するきっかけとしてもとても良いものだと思います。話が前後するかたちになりますが、説明の前にポイントをまとめておきましょうか。
- 全てのクラスは
Object
クラスの派生クラスであり、toString
メソッドを持っている。 - Java APIでは、
toString
がそのクラス相応の文字列を返すようオーバーライドによって再実装されているものがある。String
クラスはその最たる代表と言える。 System.out.println
メソッドの実体は、標準出力のPrintStream.println
である。PrintStream.println
は、String
クラス並びに根幹であるObject
クラスをも引数と取る各種のオーバーロード版のメソッドがある。PrintStream.println
メソッドは、その処理の中で引数に対してvalueOf
メソッドやtoString()
メソッドを適時実行し、文字列を出力する
です。では見ていきましょう。まず、疑問の発端となったSystem.out.println
メソッドのリファレンスを見てみます。
System.out.println から辿ってPrintStream#printlnに行き着きます。引数の型ごとにいくつもオーバーロードされたprintln
がありますが、System.out.println(a)
を実行した場合に呼ばれるメソッドは、a
はString
クラスなので、public void println(String x) です。String
ではない別のクラスであれば、Object
クラスの変数を引数とする public void println(Object x)が呼ばれます。このメソッドに関してリファレンスには次のように書いていますね。
Objectを出力して、行を終了します。このメソッドは最初にString.valueOf(x)を呼び出して出力されるオブジェクト> の文字列値を取得してから、print(String)、そしてprintln()を呼び出すのと同じように動作します。
「String.valueOf(x)
を呼び出す」そうです。a
を引数として渡す場合、String.valueOf(a)
と読み替えられます。String.valueOf
とは何でしょう。これもリファレンスを確認します。String#valueOf(Object obj)
「Object引数の文字列表現を返します」そうです。戻り値としては「引数がnullの場合は"null"に等しい文字列。それ以外の場合はobj.toString()の値が返される。」とあります。
つまり、System.out.println(a)
は、そのメソッドの中で a.toString()
を実行しています。toString()
メソッドとは何でしょう。これは、Javaのすべてのクラスの根本であるjava.lang.Objectクラスが持つ、最低限の機能を必ず実装しているメソッドです。Object#toStringデフォルトの実装ではtoString()
は単純に参照の値を出力するようものですが、String
クラスはこれをオーバーライドして、自身が管理している文字列を出力するようになっています。String
クラスが担う役割を考えると、適当ですね。
参考:
toStringメソッドのオーバーライドについて - teratial#70200
BufferedReaderクラスでは同じようなことはできませんよね。
そのままではできませんが、BufferedReader
を継承すればできます。上記も踏まえ、書いてみたサンプルプログラムが以下、です。BufferedReader
のインスタンスがtoString
で何を出力すべきかは、考えどころでしょうけれども。
Java
1import java.io.InputStreamReader; 2import java.io.Reader; 3import java.io.BufferedReader; 4 5public class Main 6{ 7 public static void main(String[] args) 8 { 9 Main obj = new Main(); 10 obj.run(); 11 } 12 13 void run() { 14 System.out.println("run"); 15 System.out.println(this); 16 System.out.println(String.valueOf(this)); 17 18 InputStreamReader isr = new InputStreamReader(System.in); 19 BufferedReader br = new BufferedReader(isr); 20 System.out.println(br); 21 22 br = new XBufferedReader(isr); 23 System.out.println(br); 24 } 25 26 @Override 27 public String toString() { 28 return "Mainクラスのインスタンスです。"; 29 } 30 31 class XBufferedReader extends BufferedReader { 32 XBufferedReader(Reader in) { 33 super(in); 34 } 35 36 XBufferedReader(Reader in, int sz) { 37 super(in, sz); 38 } 39 40 @Override 41 public String toString() { 42 return "XBufferedReaderクラスのインスタンスです。"; 43 } 44 } 45}
上記プログラムのWindowsコマンドプロンプト上での実行例です。System.out.println
の実行と照らし合わせてみてください。
CMD
1C>java --version 2java 11.0.9 2020-10-20 LTS 3Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS) 4Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, mixed mode) 5 6C>java --source 8 Main.java 7run 8Mainクラスのインスタンスです。 9Mainクラスのインスタンスです。 10java.io.BufferedReader@323b36e0 11XBufferedReaderクラスのインスタンスです。 12 13C>
投稿2021/09/10 21:03
編集2021/09/11 02:11総合スコア9267
0
String クラスは他のクラスより特別視されています。
それは(数値と並んで)普遍的な"文字列"を扱うためです。
println からすれば、「"文字列"を表示する」という機能面を考えても String を特別に扱うのは当然ではないでしょうか。
ちなみに、BufferedReader のインスタンスを println に渡すことは可能です。
何が表示されるかは、保証できませんが。
投稿2021/09/10 20:09
編集2021/09/10 20:16総合スコア13215
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/09/11 03:06
2021/09/11 03:20
2021/09/11 05:25
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/09/10 21:28
2021/09/10 21:33
2021/09/11 02:14
2021/09/11 02:17
2021/09/11 02:19
2021/09/11 02:23
2021/09/11 02:42
2021/09/11 02:47
2021/09/11 02:54
2021/09/11 06:48 編集